[Перевод] Изобретайте колесо

41864bee1028466e738cff18250dad65.png

Совет «не изобретать колесо» (в смысле «не искать собственных решений вместо использования имеющихся») плох уже потому, что переизобрести буквальное физическое колесо — довольно неплохая идея. Колеса независимо придумывались бессчётное количество раз. Менялся дизайн и пропорции; используемые материалы эволюционировали от камня и дерева до металлических сплавов, а затем и композитов. Примерно круглый плоский камень с дыркой посередине — это совсем не то же самое, что идеально круглое тонкое колесо с десятками металлических спиц.

Эволюционировали компоненты, с которыми взаимодействует колесо (например, ось и шины), так что колёса эволюционировали вместе с ними. Необходимость ездить по таким поверхностям, по которым раньше никто и не пытался проехать, тоже заставляет изобрести подходящее колесо:

726a00724d3cde1fa12879f0140f10ef.jpeg

Создателей первых колёс в истории нельзя не уважать. Но нельзя не уважать также и тех, благодаря кому за мной не приезжает такси, стоящее на более-менее округлых дырявых камнях.

При чём тут программирование

Надеюсь, деконструкция метафоры поможет понять, насколько эта метафора бесполезна в программировании. Немалая часть софта, которым мы пользуемся каждый день — это как раз переизобретённые колёса и самопальные велосипеды. Линукс — это переизобретённый Unix; MariaDB — это переизобретённый MySQL, который в свою очередь не что иное, как переизобретённый PostgreSQL/Oracle DB.

Современный C++ — это многократно переизобретённый C++, который в свою очередь является переизобретённым C (восходящим к B, который происходит от BCPL). Rust — переизобретение C++/C. Closure — это переизобретение LISP, который был переизобретением IPL и лямбда-счисления. Haskell — переизобретение System FC, который восходит к System F, который тоже восходит к лямбда-счислению. DOT — переизобретение объектов, Kotlin — переизобретение Java, Vim — переизобретение Vi, Wayland — переизобретение Xorg, systemd — переизобретение нескольких сотен разных программ, даже ядро OS X — не более чем кривое переизобретение BSD. Я могу продолжать хоть до завтра, но идея понятна.

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

Изобретайте собственные колёса, оптимизируйте их под себя — и, может быть, они пригодятся всем остальным.

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

Вот когда, на мой взгляд, стоит переизобретать колесо:

Переизобретайте колесо, если имеющиеся колёса не подходят вашей телеге

Не пишите плохое ПО только потому, что плохи имеющиеся библиотеки. Вместо этого напишите сперва библиотеку: у вас будет и хорошая программа, и код, который наверняка пригодится кому-то ещё. Получится дольше, да, но это интереснее и даёт лучшее ПО на выходе.

Разумеется, не надо отказываться от здравого смысла. Истина где-то между «программистами» на C, которые каждый раз имплементируют собственные векторы, и «разработчиками» на JavaScript, которые обеспечивают библиотеки is_odd её 100 000+ скачиваний в день. Где именно — вопрос открытый, но хорошим примером может быть Julia. Это язык программирования, который похож на Python почти во всём, кроме трёх вещей:

  • Он легко деплоится без виртуальных сред

  • Векторные операции гораздо быстрее

  • Масштабный параллелизм изначально заложен в язык

И да, для всех трёх фич можно было бы не придумывать свой язык. Есть venv, есть Cython, есть байндинги к библиотекам на C/C++. На крайний случай всегда есть возможность использовать хороший стиль программирования и приложить немного терпения.

Вот только в Julia это всё работает из коробки. Достоинства Python никуда не деваются, а отсутствие его недостатков экономит время и делает разработку куда более приятным занятием, так что Julia может стать одним из лучших языков 21 века.

Переизобретайте колесо, если его давно не переизобретали

Ещё одна причина переизобрести колесо — это если в последнее время что-то не видать новых колёс. Это означает одно из двух: возможно, имеющееся колесо действительно не нуждается в совершенствовании. Но также возможно, что многим в принципе не помешало бы колесо получше; вот только у них не доходят руки и/или они не знают, с какой стороны подступиться.

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

Хороший пример — распознавание образов классическими методами. До-нейросетевые классификаторы потихоньку эволюционировали, и к 2010 году штуки типа ядра Фишера выдавали довольно неплохие результаты. Им всё ещё нельзя было доверить автономный автомобиль или диагностику рака, но они таки достигли уровня где-то между особо сообразительным попугаем и средним слоном по точности, времени тренировки и числу распознаваемых вещей. Общепринятой мудростью было «не переизобретать велосипед, а взять имеющиеся методы и оптимизировать параметры».

А потом кто-то вспомнил про свёрточные нейросети и запустил их на современных GPU. Эти модели придумали ещё в 90х, но сочли вычислительно неподъёмными и практически забросили. В 2012 вышла знаменитая AlexNet, и в распознавании образов случился прорыв. Современные нейросети уже обходят человека на датасетах среднего размера.

Переизобретайте колесо, если оно проприетарное

Многие великие Open Source-проекты (Linux, GCC, git) — не более чем переизобретение уже существующего ПО. Даже если изначально они были хуже проприетарных аналогов, бесплатный открытый код привлекает больше пользователей, некоторые из которых начинают слать пулл-реквесты. Постепенно проект превосходит своего проприетарного предка: git и Linux — дефолтные инструменты для своих задач, а их предшественники практически забыты.

Переизобретайте колесо, если вам этого хочется

Нет ничего плохого в том, чтобы попытаться переизобрести колесо, которое и так прекрасно работает. Даже если ничего не выйдет, вы по крайней мере узнаете много нового и поймёте, почему имеющееся ПО устроено так, как оно устроено.

Многие интересные проблемы давно решены, но люди всё равно за них берутся. Миллионы пытались самостоятельно доказать теорему Пифагора или изобрести «новый LISP»; у большинства из них получалось в лучшем случае то, что уже и так имелось до них. Но почему бы и не потратить своё время, если вы тратите его с удовольствием? К тому же есть небольшой шанс таки усовершенствовать существующее колесо.

В заключение

Идите и переизобретите колесо. Если кто-то скажет, что вы занимаетесь ерундой — отвечайте, что именно так наша область и развивается. А если вам кажется, что задачу уже пытались решить до вас куда более опытные специалисты, то вспомните вот эту штуку:

d9bc87026d59f2089ea81aeb9a20ee67.jpeg

31-летний нёрд без особых познаний в астрофизике, математике или инженерии, и всего с сотней миллионов долларов, построил ракету лучше, чем у NASA, CNSA, ESA, Роскосмос, армий РФ, США и Китая, и прочих уважаемых аэрокосмических гигантов, хотя у них и были десятки тысяч учёных, сотни тысяч инженеров и миллиардные бюджеты. Так что вполне возможно, что вам по зубам создать более удобную библиотеку для рисования графиков в JS, более быстрый JIT-компилятор для Python, более дешёвые АЛУ, новый Shopify или более эффективную по памяти хэш-таблицу.

© Habrahabr.ru