Добавить в корзинуПозвонить
Найти в Дзене
Сделай игру

Как быть хорошим программистом и не быть плохим

Есть мнение, что "хороший программист" - знает всё, со всем работал и быстро во всём разбирается. Но это не так. Разобраться в новой области или овладеть ей, в текущих условиях, отнюдь не такой уж редкий навык. Хороший программист - это человек, познавший дзен командной разработки и понимающий, что то, что он делает сегодня, может стать головной болью завтра. Вот об этом я и хочу порассуждать. Чукча не читателя Вполне себе рабочий пример. У меня есть коллега, который, безусловно, считает себя хорошим программистом. Он работает на двух работах и зарабатывает очень прилично. Прямо вот так очень. Но, чёрт побери, я его совсем не считаю хорошим программистом, потому что после того, как мне приходится вносить правки в его код (а такое иногда, но случается), я каждый раз в голос матерюсь и высказываю всё, что о нём думаю. Хорошо, что он меня не слышит, т.к. работает из другого города. И причина в моём недовольстве - проста: он выбирает инструменты для реализации задумок и стиль, который прев
Оглавление

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

Если посадить сто мартышек за компьютеры и дать им возможность печатать - за сто лет они случайно напишут какое-нибудь приложение
Если посадить сто мартышек за компьютеры и дать им возможность печатать - за сто лет они случайно напишут какое-нибудь приложение

Чукча не читателя

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

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

Четыре уровня абстракций, разнесённых по разным файлам и папкам проекта (там где хватило бы одного), 2000 строк кода в главном файле подпроекта, из которых первые 100 строк - импорты, с попутным объявлением внутри новых интерфейсов и типов.

Такое можно писать только будучи в убеждении, что никто после тебя читать это не станет. Но, на практике, так почти никогда не бывает. Подумаем, как же это исправить.

Код для тех, кто читает, а не пишет

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

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

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

Однако, как только такой код попадает к человеку новому, это превращается в настоящее испытание для новичка.

Именно поэтому, следует всегда помнить, что код пишется для другого человека, а это легче делать тогда, когда самому сложно работать с плохим кодом. Для меня, повторюсь, в этом помогают упрощённые IDE (Sublime Text, Vim, NeoVIM). Однако я не призываю отказываться от любимых сред разработки. Тут - каждому своё.

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

Хотя можно и разделить экран и пополам и выводить один и тот же файл слева и справа; в этом случае предельную длину можно выбрать побольше. Но это не особо удобно.

Чем меньше импортов, тем лучше

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

Однако, давайте рассмотрим этот вопрос как некоторую иерархическую структуру (дерево), где каждый узел сосредотачивает функционал нижележащих узлов.

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

Если предположить, что количество импортов должно стремиться к числу 5 плюс-минус 2, то можно попробовать разбить сложный узел на несколько узлов, выстроенных в иерархию.

В таком случае, скорее всего, произойдёт увеличение кодовой базы без увеличения функционала (издержки на линии соединения), однако облегчится восприятие кода.

Второй немаловажный момент - количество уровней импортов. Уже при необходимости открывать третий файл, при распутывания логики работы какой-то функциональности, вызывает небольшое раздражение; что говорить, когда таких уровней, скажем, 7 (как в моём проекте)?

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

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

Таким образом, минимизация импортов в одном файле (неважно, какой механизм используется) - позволяет снизить сложность кода внутри, а вынесение набора функциональности в отдельный компонент - позволяет "сбросить" количество уровней импортов.

Каждый инструмент для подходящей задачи

Например я не люблю typescript. И это нелюбовь взаимна. Моя аргументация проста: javascript позволяет решать задачи быстро и без оглядки на формальности и правила, а, учитывая специфику работы в web - это часто оправдано. Часто, но не всегда.

Как сказал один мой коллега: "дешевле ловить ошибки в процессе разработки, нежели в продакшене". И я с ним полностью согласен: формализация и типизация позволяет избежать большого количества ошибок ещё на этапе написания кода... и создаёт настоящий ад, когда нужно выполнить небольшую правку, превращая её в приключение "подвинуть пять тонн кирпичей на 10 сантиметров вправо". С javascript такой проблемы не бывает. Но его недостатки являются продолжением достоинств: сложить строку с числом? Запросто! Только вот получится что в ответе, строка или число? Конечно строка... которая может быть интерпретирована как число... 1+1 == 11.

И вот на это я хотел бы указать! Для каждой задачи следует выбирать свой инструмент. В тех местах, кто типизация важна, т.к. речь идёт о рабоче с чувствительными данными - тот же typescript совершенно оправдан (это, чаще всего, серверная часть или отдельные модули клиентской), но когда речь идёт про вёрстку табличек из какого-нибудь antd, то совершенно непонятно, на кой чёрт там использовать вышеупомянутый typescript, если это крайне "подвижная" часть, где кочующие данные от компонента к компоненту меняются каждый релиз?

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

Однако, выбор подходящего инструмента - очень важно. Возвращаясь к примеру javascript/typescript - можно сказать однозначно, что все чувствительные к данным узлы - можно разрабатывать на typescript, а нечувствительные, но требующие гибкости - на javascript. В случае с клиентской разработкой, будет больше второго, в случае с серверной - первого.

Закостенелость мышления

И под конец, хотелось бы упомянуть и про закостенелость. Обычно, оно сводится к тому, что некоторый разработчик провёл несколько лет в работе с каким-то языком, фреймворком или технологией и хорошо её знает. А потому предлагает использовать её везде и отчаянно отказывается пробовать что-то новое или просто альтернативное.

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

Например react изначально создавался как фреймворк реактивного программирования для "лицокниги", а после, что называется, "пошёл в массы". Есть целый класс приложений (обычно, относительно статичное чтение и управление данными), где он работает отлично, но как только заходит речь о более динамичных приложениях (что-то связанное с графикой, видео или звуком, часто обновляющихся, хранящее большой объём данных долго обрабатываемого состояния), то он превращается из помощника в обузу, которую надо со всех сторон подпирать костылями.

Однако условный "закостенелый программист" будет стараться его воткнуть куда бы то ни было просто потому что он его знает. То же самое будет и с языками программирования или технологиями (скажем, vagrant или docker).

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