Как стать автором
Обновить

Не покупайте грузовик для похода за хлебом и другие принципы программирования

Уровень сложностиПростой
Время на прочтение8 мин
Количество просмотров1.8K

Мне недавно встретился код вывода количества FPS на экран, написанный начинающим программистом, и в этом коде был базовый класс, класс-потомок, виртуальные функции, конструктор с множеством параметров, variant. Код позволял выводить любое количество счетчиков FPS на экран разными шрифтами, но все, что было на самом деле нужно, это простая функция на 3 строки, считающая количество FPS и выводящая его на экран.

1. Кто ты вообще такой и с какой стати мы должны тебя слушать?

Вам должно быть стыдно, что вас все еще интересуют такие вопросы. Не важно, кто хочет вам что-то рассказать, важно лишь, что именно он рассказывает. Вы должны понимать, что люди получают все более высокий статус до тех пор, пока не оказываютя в таком месте, где они совершенно некомпетентны, и большую часть времени они пребывают именно в таком положении, так что меньше внимания обращайте на должности и статусы, думайте о том, что вам говорят, а не о том, кто вам говорит. Если вам так важно, то считайте, что я вообще говорящая собака. Довольны? Теперь мы можем перейти к делу?

2. Что чаще всего является признаком правильно написанной программы?

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

3. Какие типичные ошибки допускают программисты, особенно начинающие, и как их избежать?

Самая распространенная ошибка — преждевременная оптимизация и излишнее усложнение. Молодые программисты часто создают сложные архитектуры и абстракции "на вырост", которые в итоге никогда не пригодятся. Они строят иерархии классов там, где достаточно простой функции, или разрабатывают гибкие интерфейсы для функциональности, которая никогда не будет расширяться. Это как купить огромный шкаф для одежды, когда у тебя всего две футболки и джинсы, или приобрести грузовик для поездок за батоном хлеба в магазин за углом и парковать его в многоэтажном паркинге, который дальше от вашего дома, чем магазин.

Еще одна ошибка — слепое следование принципам без понимания их контекста. "Глобальные переменные — зло", "goto — плохо", "всегда используйте ООП" — можно сказать, что эти правила имеют свои исключения, и настоящее мастерство приходит с пониманием, когда их можно нарушить, но на самом деле это не правила, это какие-то ничем не обоснованные утверждения, которые вы по наивности приняли на веру. Например, если вы пишете код для тостера, вам вряд ли понадобится сложная объектная модель с наследованием и полиморфизмом. Это как надевать смокинг для похода в сауну — технически возможно, но все будут задаваться вопросом о вашем психическом состоянии.

Чтобы избежать этих ошибок, нужно постоянно задавать себе вопрос: "Действительно ли такая возможность необходима прямо сейчас?" Пишите код для решения текущих, а не гипотетических будущих проблем. Гипотетические будущие проблемы могут и не наступить, а вот код останется готов к решению именно этих проблем, и когда возникнут совершенно другие проблемы, решать их может оказаться гораздо сложнее, чем если бы код был проще. Мои любимы принципы: YAGNI (You Aren't Gonna Need It) и KISS (Keep It Simple, Stupid).

4. С чего начинать и как организовать работу над большим проектом?

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

Важно начать с простого решения и постепенно его развивать. Хорошо себя зарекомендовал итеративный подход: сделать что-то работающее, получить обратную связь, улучшить. Это позволяет быстрее выявлять настоящие проблемы и лучше понять, какие на самом деле требования к проекту. Мало того, что все, в том числе и заказчики, постоянно врут, так они еще и сами не знают, что они хотят. И хуже всего, если заказчик ты сам - в таком случае ты тож не знаешь, чего хочешь, и еще и врешь себе, что знаешь.

Что касается организации кода, стоит избегать создания излишних абстракций на ранних этапах. Архитектура должна развиваться вместе с пониманием проблемы, а не быть высеченной в камне с самого начала. Каждая лишняя абстракция, которая не пригодилась, не упрощает, а усложняет развитие проекта.

5. Какие инструменты или подходы в программировании наиболее полезны и эффективны в повседневной деятельности?

Самый полезный "инструмент" — это ясное мышление и способность разбивать сложные проблемы на простые части. Никакой IDE или фреймворк не заменит этого. Если вы не можете объяснить свою программу резиновой уточке, то, скорее всего, вы сами не понимаете, что написали.

Из конкретных практик можно выделить:

  • Написание тестов — они не только ловят ошибки, но и помогают лучше продумать дизайн кода.

  • Регулярный рефакторинг — поддержание кода в чистоте окупается многократно.

  • Нельзя документировать неочевидные моменты: если код неочевиден и не понятен другим людям сейчас, то в будущем он станет непонятен и тебе, и документация может не помочь. Точно поможет переписать код так, чтобы не было неочевидных моментов.

Что касается технических инструментов, обратите внимание на те, что не навязывают определенный способ мышления, а расширяют возможности. Хороший редактор кода, система контроля версий, инструменты статического анализа — все это помогает, но не заменяет понимания сути проблемы.

6. Как тренировать навыки правильного программирования? Какие можно дать практические рекомендации тем, кто начинает заниматься программированием или хочет улучшить свои навыки?

Самый эффективный способ — это писать код и получать обратную связь. Читайте код других людей, особенно хорошо спроектированных проектов с открытым исходным кодом. Анализируйте, почему они сделали именно такой выбор. Особенно хорошо, если этот код уже достаточно взрослый и доставляет массу проблем, как, например, Linux. Это как учиться водить на старой машине: если справишься с ней, то справишься с любой.

Практические рекомендации:

  • Решайте реальные проблемы, а не абстрактные упражнения. Не создавайте библиотеки, если вам нужно меньше трех реальных приложений, использующих эти библиотеки.

  • После написания работающего кода, потратьте время на его улучшение. Помните, что код — это не вино, с годами он лучше не становится. Скорее, это как молоко — если оставить его надолго, оно превратится в нечто непредсказуемое, что никто не хочет трогать.

  • Регулярно пересматривайте свой старый код — это отличный способ увидеть свой прогресс и понять типичные ошибки. Иногда это похоже на просмотр старых фотографий: "Неужели я действительно так выглядел?" или "Кто разрешил мне писать этот алгоритм сортировки? Я же явно был не в себе".

  • Объясняйте свои решения другим — это заставляет структурировать мысли.

  • Не бойтесь экспериментировать с разными подходами к одной и той же задаче.

И самое главное — развивайте "чувство простоты". Умение создать простое, элегантное решение — это высшая форма мастерства.

7. Некоторые программисты стремятся писать код как можно быстрее или использовать самые современные фреймворки в ущерб качеству кода и архитектуры. Как найти правильный баланс между скоростью и качеством?

Это ложная дихотомия. В долгосрочной перспективе качественный код позволяет двигаться быстрее. Конечно, в краткосрочной перспективе можно получить временное преимущество, написав "быстрый и грязный" код, но вы будете расплачиваться за это снова и снова при каждом изменении. Это как брать микрокредиты для оплаты предыдущих микрокредитов — сначала кажется, что ты решаешь проблему, а потом внезапно оказывается, что ты должен три почки, хотя у тебя их всего две.

И под грязным кодом я подразумеваю вовсе не "плохой код, использующий плохие практики", а ленивый код, который не был улучшен после того, как он перестал быть новым, попытки применять новые возможности языка или паттерны там, где без них код вышел бы короче, понятнее и проще.

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

Что касается новых возможностей языков — я предпочитаю консервативный подход. Новые технологии должны решать реальные проблемы, а не использоваться ради галочки в резюме. Прежде чем применять новые возможности или вообще новые языки, задайте себе вопрос: "Какую конкретную проблему он решает лучше, чем существующие инструменты? Правда ли это так, или я стал жертвой рекламы? Чем на самом деле мне придется расплатиться за это?"

Рассмотрим, как неуместное применение облегчающих в моменте написание кода возможностей приводит к проблемам. Для начала, согласитесь, что при модификации и отладке кода его часто приходится читать, и при чтении кода в голове нужно держать цель этого чтения, набор гипотез о том, в каких состояниях находятся разные части программы, значения и типы нескольких переменных. Обычно в голове помещается всего 5-7 вещей, а дальше новые вещи вытесняют старые. Допустим, вы уже держите в голове несколько важных вещей и пытаетесь понять, будет ли выполняться ветка А или B. А в коде встречается вот такая конструкция:

auto result = some_function(some_args);
if (result.Get()) {
  /*A*/ 
} else {
  /*B*/ 
}

Для понимания, что может происходить, нужно найти определение функции some_function() и посмотреть, какого типа возвращаемый результат, и что возвращает функция Get() у этого типа. Если тип окажется сложным, может быть, придется искать базовый класс, и так далее. Весьма вероятно, что к концу чтения вы забудете, что именно вы хотели проверить, или потеряете часть важных вещей, которые до этого держали в голове.

8. Есть ли сейчас какие-то специфические тренды или технологии, за которыми в обязательном порядке следует следить, чтобы оставаться востребованным специалистом?

Технологии приходят и уходят, но фундаментальные принципы остаются. Я рекомендую обращать внимание не столько на конкретные фреймворки или языки, сколько на подходы к решению проблем.

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

Важнее конкретных технологий — умение быстро учиться и адаптироваться. Востребованный специалист — это не тот, кто знает все фреймворки, а тот, кто может быстро освоить новый инструмент, когда это действительно необходимо. Это как уметь пользоваться картой вместо того, чтобы заучивать наизусть маршруты до каждого возможного места назначения.

9. Какой главный совет можно дать тем, кто хочет «правильно» писать программы и развиваться в профессии?

Стремитесь к простоте. Умение создать простое, понятное решение сложной проблемы — это высшее мастерство в программировании. Не поддавайтесь искушению добавить лишнюю абстракцию или использовать модный паттерн только потому, что вы его недавно изучили. Это как пытаться использовать новый кухонный комбайн для приготовления всего подряд, даже когда нужно просто нарезать один огурец.

Пишите код для людей, а не для компьютеров. Компьютер выполнит любой синтаксически корректный код, но ваши коллеги (и вы сами через полгода) должны его понимать. Представьте, что через полгода ваш код будет разбирать слегка раздраженный человек с бензопилой, и этот человек знает, где вы живете.

И, наконец, никогда не переставайте учиться, но учитесь критически. Не принимайте на веру догмы и "лучшие практики" — понимайте, почему они работают и в каком контексте. Настоящий профессионализм — это знание, когда следовать правилам, а когда их нарушать.

Программирование — это в конечном счете искусство коммуникации. И как в любом искусстве, истинное мастерство проявляется не в сложности, а в элегантной простоте.

10. Если твое, читатель, мнение отличается от вышеизложенного, я с большим интересом почитаю твои ответы на эти вопросы.

Теги:
Хабы:
+18
Комментарии9

Публикации

Истории

Работа

Программист C++
78 вакансий
QT разработчик
3 вакансии

Ближайшие события

25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань