История моего печального опыта увлеченности преждевременной оптимизацией
Я думаю многие разработчики слышали о преждевременной оптимизации, вредность которой явно подчеркивал Дональд Кнут в своей знаменитой фразе: "Преждевременная оптимизация - корень всех зол". Есть немало людей, которые не считают это какой-либо серьезной проблемой и когда я только начинал программировать я тоже легкомысленно к этому относился но со временем набив немало шишек на своей опрометчивости я стал более серьезно относиться к этой проблеме. В общем обо всем этом и хочу рассказать.
Сразу отмечу что речь идет не об уместной или неуместной оптимизации, а именно о преждевременной (которая очевидно тоже неуместная). Из-за этой невнимательности нередко происходят холивары, поскольку у некоторых широко размыта та граница когда оптимизация является еще преждевременной, а когда ее уже поздно делать. Например небезызвестный Мартин Фаулер в своих книгах про рефакторинг часто ссылается на то, что оптимизацию надо делать только там где это нужно, имея на руках результаты профайлинга и различных показателей. Я придерживаюсь схожего мнения. В остальных случаях на мой взгляд полезно придерживаться старой поговорки матерых сисадминов: "работает - не трожь".
Коварство увлеченности преждевременной оптимизацией у малоопытных разработчиков
Тем не менее у некоторых разработчиков бывает момент когда код еще пишется, но уже зудит желание какую-то часть переписать более оптимизированно, хотя при этом еще не известно, а нужна ли именно эта оптимизация кому-либо вообще. Просто видимо в этот момент включается какая-то профессиональная педантичность, идейность, своеобразный профессиональный вызов или еще какой-нибудь внутренний фактор, а отказаться от этой затеи уже не позволяет профессиональная гордость. И хорошо если профессиональный опыт позволит своевременно перебороть это желание и подойти к этой проблеме рассчетчиво и с холодной головой.
А вот если профессионального опыта мало, то ситуация с заинтересованностью заняться преждевременной оптимизацией становится очень коварной для начинающих разработчиков. Тут стоит вспомнить про известный эффект Даннинга-Крюгера, согласно которому малоопытный специалист в силу своей низкой квалификации на определенном этапе склонен переоценивать свои навыки, при этом не осозновая свой низкий уровень квалификации. При этом потом происходит эффект холодного душа и осознание реальности со снижением уверенности в своих силах, а уже потом со временем всё как-то стабилизируется. Это я постарался как-то упрощенно описать суть эффекта.
Так вот когда у малоопытного разработчика наступает момент завышенной самоуверенности в своих навыках, а также появляется желание сразу написать самый правильный идеальный супероптимизированный код, то нередко это приводит к печальным последствиям на проекте и срывам сроков. К сожалению в такой ситуации когда-то оказался и я и это стало для меня в свое время довольно неприятным уроком.
Как я на себе познал деструктивность увлеченностью преждевременной оптимизацией
Где-то лет 20 назад когда я был еще совсем новичком в программировании я в основном занимался созданием сайтов на PHP (но уже на 5-ой версии!). И как и многие в то время PHP-программисты я даже делал свою CMS думая что уж у меня то она получится самой лучшей и правильной. Очевидно я тогда был еще очень молодым и малоопытным, но при этом имел много сил для того чтобы кодить чуть ли не круглосуточно и фанатично переизобретать свои уникальные велосипеды. Конечно это было глупо но как ни странно это помогло довольно неплохо изучить стандартные возможности PHP5, так что не могу назвать совсем уж такой опыт бесполезным.
В то время я еще и фрилансил и конечно же часто применял свои самодельные наработки, поскольку я их знал лучше всего, а большинство готовых решений мягко говоря недолюбливал. Опыта в плане организации разработки конечного продукта было очевидно мало и я больше наслаждался самим процессом программирования чем результатом. Тем не менее это всё как-то криво и косо, но решало поставленные задачи, да и в то время был стремительный рост веб-разработки на PHP, поэтому даже при таком раскладе было на чем набивать шишки опыт.
Так вот, проблема была даже не в том, что я переизобретал велосипеды, а то что в какой-то момент времени я незаметно для себя увлекся так называемой преждевременной оптимизацией при создании собственных решений на PHP, что в итоге сыграло со мной злую шутку и это с учетом того, что как я уже сказал, я не очень любил брать готовые решения. Люди с опытом сразу поймут что такая смесь приведет к беде, но к сожалению тогда рядом со мной не было более опытных людей, которые вовремя бы остановили меня от этого.
В то время в футере сайтов многие web-мастера (web-разработчиков тогда часто так называли) указывали за сколько миллисекунд была сгенерирована страничка. И я фанатично стал озадачиваться максимальным снижением времени генерации страницы и крохоборствовать за каждые микросекунды. Это все шло во вред качеству и простоте кода, с потерей кучи времени и очевидно с мизерным результатом.
Я повально избегал использования регулярных выражений, знал какие функции работают чуть быстрее других, даже стал предпочитать одинарные кавычки только потому что они выводят текст как есть, не тратя ресурсы на обработку переменных внутри строки как в случае с двойными кавычками. Кешировал всё что возможно. Избегал использования геттеров и сеттеров (магические методы __get и __set) поскольку они работали чуть медленнее прямых вызовов. Ну и еще куча всякой чепухи.
Помимо этого я еще и погрузился в профилирование скорости работы PHP скриптов и отдельных функций с помощью XDebug, результаты которого я изучал через KCacheGring. Конечно же самыми долгими операциями были не простейшие какие-нибудь строковые функции, а обычно функции соединения с базой данных и прочие с ними операции. И конечно же я стал искать способы уменьшения взаимодействия с базами данных, чрезмерно кешируя всё что возможно, фактически усложняя поддержку консистентности данных.
Конечно же при этом всём качество кода, его надежность и читаемость были на низком уровне. Да и времени на всё это тратилось просто уйма, еще и кучу раз всё переписывалось. И при этом я не замечал тот факт, что как таковой проблемы медленной скорости генерации страничек в общем-то и не было. Это только я гнался за миллисекундами, там где это нафиг и не нужно было. Соответственно стали появляться срывы сроков, нервы и сопутствующий стресс. Грустно это признавать, но что было, то было.
Даже потом, работая в одной из веб-студий, где была собственная CMS, в ней помню использовался шаблонизатор Smarty. И в студии я обязан был использовать этот шаблонизатор, но как и всё готовое он мне казался медленным и неудобным и вне работы я конечно же переизобретал свой собственный самый быстрый и удобный очередной шаблонизатор. Т.е. я опять стал тратить кучу времени впустую, вместо того, чтобы взять проверенное готовое решение и акцентрироваться именно на решении задачи.
Конечно спустя годы набрав опыта я с грустью стал осозновать насколько это было тогда бредовым и сколько было потеряно драгоценного времени в пустоту. Но время уже не вернуть назад и остается разве что трезво анализировать ту ситуацию.
Со временем, когда я научился не только программированию, но и менеджменту, я стал на проекты смотреть более широко, переключая внутри себя роли "программиста" и "менеджера". Некоторые принципы из менеджмента вообще неплохо так в разработке помогают остужая мимолетное желание сделать совершенный по производительности код, возвращая к реальности с осознанием ограниченности ресурсов на разработку.
Общее отношение к оптимизации как к процессу
Если отойти именно от преждевременной оптимизации, то реально уместную и своевременную оптимизацию я считаю очень важной и полезной. Но я не считаю этот процесс простым и соответственно за него лучше браться при наличии достаточно опыта в разработке и имея широкий взгляд на проект, а новичкам наверное лучше в первую очередь научиться просто закрывать задачи полноценно и вовремя.
Также я очень люблю изучать и использовать сторонние хорошо оптимизированные и отлаженные программные решения. Это кстати одна из причин, почему мне нравится изучать как разработчики в свое время делали игры под первую Playstation. Но это все были уместные оптимизации, которые реально было необходимы и выгодны, да и делались людьми с опытом.
В общем можно сказать что к программным оптимизациям у меня всё равно остался профессиональный интерес но я уже давно подхожу к нему с учетом практичности и выгоды. Если есть реальная подтвержденная нужда в оптимизации, которая несет в себе ощутимую выгоду (по времени, деньгам, репутации и пр.), то такой оптимизацией мне нравится заниматься ибо я чувствую, что решаю реальную, а не какую-то абстрактную проблему, ибо в ином случае это просто потеря драгоценного времени. Да и профессиональная гордость за себя появляется, когда коллеги или пользователи реально подтверждают эффект от оптимизации.
Возможно из-за страсти к практической оптимизации мне стала нравится разработка на микроконтроллерах, поскольку там навыки качественной оптимизации важны из-за ограниченности ресурсов. Причем это касается даже в случае разработки на Micropython, как бы это странно не звучало.
Заключение
В общем если кому-то и просто на словах было понятно, что увлеченность преждевременными оптимизациями приводит к беде, то я когда-то по неопытности и излишней самоуверенности испытал это на практике лично. Но признавать ошибки так или иначе надо, это как минимум первый шаг к исправлению. Не ошибается тот кто ничего не делает. Да и негативный опыт, тоже опыт.
Также я научился спокойно относиться к чужому коду, какой бы он не был. И если я вижу сильно неоптимальный код я допускаю что разработчик возможно писал такой код из-за ограниченности времени и других ресурсов и в силу своего опыта принял наиболее оптимальное решение, чтобы хоть так, но решить задачу. И это лучше чем долго оптимизировать и не довести работу до конца.
Ну и еще стоит добавить, что начинающим разработчикам стоит нарабатывать первый опыт не в одиночку, а в команде с более опытными разработчиками. Так у вас будет меньше шансов потерять кучу времени на глупых ошибках в следствие отсутствия опыта. Потерянное время вам никто не вернет, так что цените свое время.