Некоторое время назад в одной из своих статей я описал понятие пластилиновой архитектуры. В продолжение я бы хотел описать один из самых распространённых «стилей программирования», который, к сожалению, очень часто встречается у молодых и неопытных специалистов.
Итак, давайте представим, что перед программистом стоит задача написать новый модуль или дописать некоторую функциональность к уже существующей системе. Что будет делать опытный специалист? Он нальёт себе китайского чая, откинется на спинку кресла, возьмёт карандаш и начнёт думать. Он нарисует структуру модуля, обдумает сущности, интерфейсы и взаимодействие между ними, опустится на уровень конкретных методов, вероятно, напишет юнит-тесты на интерфейсы. Только потом он начнёт наполнять кодом существующую структуру (либо делегирует эту задачу десятку индусов-кодеров).
Теперь давайте посмотрим, как поступит в этом случае типичный джуниор. Есть задача – её надо решить. Их так учили в университетах. Многие из них ещё находятся под влиянием маргинального лозунга «пиши код, б##дь!». Итак, он наливает себе растворимого кофе, надевает наушники с чем-нибудь пожёстче и погромче и уходит в поток на пару-тройку часов.
Всё бы ничего. Я ничего не имею против кофе, наушников или состояния потока. Более того, обычно это наиболее эффективный и, зачастую, единственный способ писать хороший код. Но мы рассматриваем типичный случай молодого и неопытного программиста, поэтому давайте посмотрим на результаты.
Во-первых, функциональность реализована. Она работает на большинстве кейсов и выглядит вполне себе удовлетворительной. Первое, что хочется сделать – это порадоваться, что молодой специалист так быстро справился с задачей, похвалить его и дать следующую. Но попробуйте заглянуть в код. Вам сразу станет понятно, почему фрагмент был реализован так быстро. И станет страшно.
Перед вами код, который я обычно называю «дамп потока сознания» . Я называю код именно так, потому, что он пишется единым блоком, без попытки осознать его, без попытки вернуться и что-то изменить. Ниже я перечислю его основные характеристики.
Во-первых, код обычно состоит из одного длинного, очень длинного метода. В нём, например, может последовательно происходить инициализация соединения с базой данных, формирование нужного запроса, получение данных, их обработка и (пусть это будет вебдев) формирование HTML для итогового представления. Автор пишет о том, о чём он думает в данный момент, он полностью в потоке и сосредоточен на решении задачи. Его сознание поэтапно решает задачу и эти шаги незамедлительно отражаются в коде.
Во-вторых, этот код, обычно, переполнен закомментированными строчками и ненужными больше кусками, которые выкинуть жалко и оставлять не нужно.
В-третьих, обычно в таком коде обрабатываются только основные варианты использования, стандартные условия и ветвления. При небольшом отклонении от стандартного поведения пользователя, код нещадно сбоит и падает с необработанными исключениями.
Частично об этом я написал чуть выше, но есть ещё достаточно большое число факторов, о которых необходимо сказать.
Самое большое зло от такого кода – это абсолютная невозможность его сопровождать. Действительно, через несколько дней не только «человек с улицы», но и сам автор не сможет понять, что происходит внутри этого куска, и за что отвечает это ветвление. Очевидно, что поддержкой такого кода программисты, в том числе и автор, будут заниматься не только неохотно, но и крайне неэффективно.
Кстати, это будет влиять не только на цели проекта, затягивая сроки и понижая качество, что, несомненно расстроит ПМа. Работа с таким кодом будет серьёзно подрывать мотивацию команды сразу с двух направлений, лишая программиста излюбленных сторон его работы: «я делаю что-то крутое и интересное» и «я отлично справляюсь со своей задачей».
Ещё одно из больных и неприятных свойств «дампа потока сознания» состоит в том, что проблемы не видны сразу, так как с первого взгляда «всё работает». Очень часто, тестируя такой код (естественно, по принципу чёрного ящика), тестировщик сталкивается с багами, воспроизводить которые очень тяжело. Обычно они возникают из-за переплетённой, полностью лишённой структуры массы вызовов и связанных с ней неявных «наводок», когда один кусок кода совершенно удивительным образом влияет на другой.
Таким образом, в копилку «жертв» к уже имеющимся там программисту и руководителю проектов, добавляется специалист по тестированию. И, в заключение, чтобы собрать под этим дырявым зонтом полную проектную команду, добавим, что менеджер продукта (или заказчик в случае заказной разработки) не может эффективно добавлять в продукт новые фичи, а аналитик не имеет понятия о том, реально ли сделать минимальное изменение, и не услышит ли он заоблачных сроков (а то и нецензурных выражений) от программистов за простое предложение «чуть-чуть изменить работу поискового фильтра».
Вывод простой: «дамп» – это зло, с которым надо бороться.
Чтобы данная статья не была слишком теоретической, попробую дать несколько советов, как это делать, которые я применяю на практике у себя в компании.
Первое и самое важное, что надо понять, когда вы сталкиваетесь с таким кодом – «это нормально».
Если вы ещё не начали бороться с «дампами» (и этого не делал ваш предшественник), то, вероятнее всего, у вас в команде есть несколько программистов, которые пользуются именно таким подходом, абсолютно искренне считая, что всё делают правильно.
Велика вероятность, что также злоупотребляют «дампами» новички, взятые в вашу команду прямо со студенческой скамьи.
И это нормальное поведение вчерашнего студента, перед которым стоит задача, и который должен её выполнить. Он видит цель – реализовать нужную фичу, но не понимает, что создавая плохой код, не приближается, а только отдаляется от неё.
Итак, первое, что надо сделать для борьбы с «дампами» — это ввести регулярные инспекции кода.
Если у вас в команде есть опытный специалист, понимающий «дух и букву» хорошей архитектуры, правильной декомпозиции, прозрачного кода и прочих правил хорошего тона, то первые инспекции нужно поручать именно ему.
При этом и ему, как исполнителю, и вам, как руководителю, необходимо понимать, что цель инспекций не устроить выволочку нерадивому кодеру, а научить его писать правильно и «заразить» любовью к красивому (без излишеств!) коду и архитектуре.
Если ваша команда состоит из новичков и такого специалиста нет – придётся воспитывать его самостоятельно.
Улучшение кода лучшее всего начать с разделения больших (иногда просто огромных) методов на маленькие и аккуратные. Обычно достаточно спросить у программиста, что делает тот или иной кусок по шагам и вынести эти шаги в отдельные методы. Затем нужно разделить каждый из методов по той же схеме (есть такое слово — рекурсия) до тех пор, пока смысл каждого не будет простым и понятным. Я планирую описать этот рекурсивный подход более детально в одной из следующих статей.
Кроме того, можно легко установить правило «не писать методы более 20 строк длиной» и проверять его на инспекциях. Программист будет вынужден размышлять о том, как разделить его «дамп», чтобы не нарушить установленные «стандарты». Конечно, это правило, как и любые другие, нельзя рассматривать как догму. Я легко могу представить метод, для описания которого придётся использовать гораздо больше, чем 20 строк. Но, в любом случае, программист будет задумываться об этом, делая процесс написания кода более осмысленным.
На самом деле, задуматься – это уже очень большой и, часто, решающий шаг на пути к качественному коду.
Далее по той же схеме можно научить программиста делить один класс на несколько, организуя последние в виде слоёв и модулей и так далее.
Но это уже другая история. А сейчас программист удивлённо смотрит на вас и не понимает, почему его замечательный метод, на который ушло два дня работы и который «делает так, чтобы всё работало» вам, вдруг, не понравился.
Объясните ему!
Итак, давайте представим, что перед программистом стоит задача написать новый модуль или дописать некоторую функциональность к уже существующей системе. Что будет делать опытный специалист? Он нальёт себе китайского чая, откинется на спинку кресла, возьмёт карандаш и начнёт думать. Он нарисует структуру модуля, обдумает сущности, интерфейсы и взаимодействие между ними, опустится на уровень конкретных методов, вероятно, напишет юнит-тесты на интерфейсы. Только потом он начнёт наполнять кодом существующую структуру (либо делегирует эту задачу десятку индусов-кодеров).
Теперь давайте посмотрим, как поступит в этом случае типичный джуниор. Есть задача – её надо решить. Их так учили в университетах. Многие из них ещё находятся под влиянием маргинального лозунга «пиши код, б##дь!». Итак, он наливает себе растворимого кофе, надевает наушники с чем-нибудь пожёстче и погромче и уходит в поток на пару-тройку часов.
Всё бы ничего. Я ничего не имею против кофе, наушников или состояния потока. Более того, обычно это наиболее эффективный и, зачастую, единственный способ писать хороший код. Но мы рассматриваем типичный случай молодого и неопытного программиста, поэтому давайте посмотрим на результаты.
Как это выглядит
Во-первых, функциональность реализована. Она работает на большинстве кейсов и выглядит вполне себе удовлетворительной. Первое, что хочется сделать – это порадоваться, что молодой специалист так быстро справился с задачей, похвалить его и дать следующую. Но попробуйте заглянуть в код. Вам сразу станет понятно, почему фрагмент был реализован так быстро. И станет страшно.
Перед вами код, который я обычно называю «дамп потока сознания» . Я называю код именно так, потому, что он пишется единым блоком, без попытки осознать его, без попытки вернуться и что-то изменить. Ниже я перечислю его основные характеристики.
Во-первых, код обычно состоит из одного длинного, очень длинного метода. В нём, например, может последовательно происходить инициализация соединения с базой данных, формирование нужного запроса, получение данных, их обработка и (пусть это будет вебдев) формирование HTML для итогового представления. Автор пишет о том, о чём он думает в данный момент, он полностью в потоке и сосредоточен на решении задачи. Его сознание поэтапно решает задачу и эти шаги незамедлительно отражаются в коде.
Во-вторых, этот код, обычно, переполнен закомментированными строчками и ненужными больше кусками, которые выкинуть жалко и оставлять не нужно.
В-третьих, обычно в таком коде обрабатываются только основные варианты использования, стандартные условия и ветвления. При небольшом отклонении от стандартного поведения пользователя, код нещадно сбоит и падает с необработанными исключениями.
Почему это плохо
Частично об этом я написал чуть выше, но есть ещё достаточно большое число факторов, о которых необходимо сказать.
Самое большое зло от такого кода – это абсолютная невозможность его сопровождать. Действительно, через несколько дней не только «человек с улицы», но и сам автор не сможет понять, что происходит внутри этого куска, и за что отвечает это ветвление. Очевидно, что поддержкой такого кода программисты, в том числе и автор, будут заниматься не только неохотно, но и крайне неэффективно.
Кстати, это будет влиять не только на цели проекта, затягивая сроки и понижая качество, что, несомненно расстроит ПМа. Работа с таким кодом будет серьёзно подрывать мотивацию команды сразу с двух направлений, лишая программиста излюбленных сторон его работы: «я делаю что-то крутое и интересное» и «я отлично справляюсь со своей задачей».
Ещё одно из больных и неприятных свойств «дампа потока сознания» состоит в том, что проблемы не видны сразу, так как с первого взгляда «всё работает». Очень часто, тестируя такой код (естественно, по принципу чёрного ящика), тестировщик сталкивается с багами, воспроизводить которые очень тяжело. Обычно они возникают из-за переплетённой, полностью лишённой структуры массы вызовов и связанных с ней неявных «наводок», когда один кусок кода совершенно удивительным образом влияет на другой.
Таким образом, в копилку «жертв» к уже имеющимся там программисту и руководителю проектов, добавляется специалист по тестированию. И, в заключение, чтобы собрать под этим дырявым зонтом полную проектную команду, добавим, что менеджер продукта (или заказчик в случае заказной разработки) не может эффективно добавлять в продукт новые фичи, а аналитик не имеет понятия о том, реально ли сделать минимальное изменение, и не услышит ли он заоблачных сроков (а то и нецензурных выражений) от программистов за простое предложение «чуть-чуть изменить работу поискового фильтра».
Вывод простой: «дамп» – это зло, с которым надо бороться.
Чтобы данная статья не была слишком теоретической, попробую дать несколько советов, как это делать, которые я применяю на практике у себя в компании.
Как с этим бороться
Первое и самое важное, что надо понять, когда вы сталкиваетесь с таким кодом – «это нормально».
Если вы ещё не начали бороться с «дампами» (и этого не делал ваш предшественник), то, вероятнее всего, у вас в команде есть несколько программистов, которые пользуются именно таким подходом, абсолютно искренне считая, что всё делают правильно.
Велика вероятность, что также злоупотребляют «дампами» новички, взятые в вашу команду прямо со студенческой скамьи.
И это нормальное поведение вчерашнего студента, перед которым стоит задача, и который должен её выполнить. Он видит цель – реализовать нужную фичу, но не понимает, что создавая плохой код, не приближается, а только отдаляется от неё.
Итак, первое, что надо сделать для борьбы с «дампами» — это ввести регулярные инспекции кода.
Если у вас в команде есть опытный специалист, понимающий «дух и букву» хорошей архитектуры, правильной декомпозиции, прозрачного кода и прочих правил хорошего тона, то первые инспекции нужно поручать именно ему.
При этом и ему, как исполнителю, и вам, как руководителю, необходимо понимать, что цель инспекций не устроить выволочку нерадивому кодеру, а научить его писать правильно и «заразить» любовью к красивому (без излишеств!) коду и архитектуре.
Если ваша команда состоит из новичков и такого специалиста нет – придётся воспитывать его самостоятельно.
Улучшение кода лучшее всего начать с разделения больших (иногда просто огромных) методов на маленькие и аккуратные. Обычно достаточно спросить у программиста, что делает тот или иной кусок по шагам и вынести эти шаги в отдельные методы. Затем нужно разделить каждый из методов по той же схеме (есть такое слово — рекурсия) до тех пор, пока смысл каждого не будет простым и понятным. Я планирую описать этот рекурсивный подход более детально в одной из следующих статей.
Кроме того, можно легко установить правило «не писать методы более 20 строк длиной» и проверять его на инспекциях. Программист будет вынужден размышлять о том, как разделить его «дамп», чтобы не нарушить установленные «стандарты». Конечно, это правило, как и любые другие, нельзя рассматривать как догму. Я легко могу представить метод, для описания которого придётся использовать гораздо больше, чем 20 строк. Но, в любом случае, программист будет задумываться об этом, делая процесс написания кода более осмысленным.
На самом деле, задуматься – это уже очень большой и, часто, решающий шаг на пути к качественному коду.
Далее по той же схеме можно научить программиста делить один класс на несколько, организуя последние в виде слоёв и модулей и так далее.
Но это уже другая история. А сейчас программист удивлённо смотрит на вас и не понимает, почему его замечательный метод, на который ушло два дня работы и который «делает так, чтобы всё работало» вам, вдруг, не понравился.
Объясните ему!