Поиск  
Always will be ready notify the world about expectations as easy as possible: job change page
24 марта

Умные программисты пишут STUPID-код

Умные программисты пишут STUPID-код
Источник:
Просмотров:
836

Умные программисты пишут STUPID-код, ведь они понимают, что неожиданно возникшая сложность может привести к провалу проекта.

▍ Страдание

На момент написания этой статьи на моих часах 21:30.

Этим утром я проснулся в хорошем, оптимистичном настроении, рассчитывая на прекрасный день, но теперь вымотан.

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

Если конкретнее, при написании или поддержке кода мы склонны постоянно попадать в ловушку случайной сложности. Я наблюдал это с первого дня попадания в эту отрасль, и эта тема стала основной темой моей презентации, посвящённой техническому долгу (Purging the Technical Debt by Using Static Code Analysis Tools на YouTube).

На появление во мне любви к разработке ПО чрезвычайно сильно повлиял Фредерик Брукс, написавший сборник эссе под названием «Мифический человеко-месяц».

В этой книге Брукс проливает свет на два типа сложности, очень хорошо вербализованных Эдрианом Колье в его блоге The Morning Paper постом No Silver Bullet — essence and accident in software engineering:

Брукс рассматривает сложности, возникающие при разработке ПО, и разделяет их на два вида: принципиальные сложности, которые неотъемлемо связаны с природой ПО; и случайные сложности, когда мы усложняем жизнь себе больше, чем это необходимо, и сложность при этом не является неотъемлемой для процесса. От случайных сложностей мы можем постепенно избавиться, но принципиальные остаются всегда.

▍ Допущение

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

Люди — не роботы. Мы эмоциональные существа. У нас бывают взлёты и падения. Мы
не понимаем полностью всего, за что берёмся, а иногда делаем свои допущения истиной. К тому же мы ленивы и непредсказуемы. Всего этого должно быть достаточно, чтобы понять или представить, почему при написании кода мы обычно стремимся двигаться по лёгкому пути, приводящему нас в город неожиданной сложности.

Но в то же время мы и увлекающиеся существа.

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

И мы умные.

Мы очень умные.

Но в то же время ленивые, непредсказуемые, эмоциональные и так далее.

▍ Предложение

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

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

Например, если вы хотите улучшить качество кода, то выбираете придерживаться принципов программирования SOLID. Я согласен с принципами и идеями SOLID. Лично я считаю, что резюмировать их основу можно как корректную реализацию объектно-ориентированного программирования со стремлением правильно делать правильные вещи. Однако когда я занимался консалтингом, то заметил, что многие люди восхваляют принципы SOLID, не уделяя внимания их ценностям, что часто приводит к созданию хрупкого кода (по перечисленным выше причинам). Когда я просил их сформулировать своими словами то, что они по-настоящему понимают в SOLID, то обычно получал неполные, неструктурированные, неуверенные ответы. Возможно, так получалось потому, что большинство принципов немного абстрактно.

Умные люди обычно обладают способностью объяснять сложные или абстрактные понятия людям любых возрастов. Вульгаризируя и применяя метафоры, они способны аккуратно объяснить сложное понятие даже ребёнку. И все мы знаем, что если ты можешь объяснить что-то ребёнку, а ребёнок понимающе кивает, то велика вероятность того, что ты сам хорошо понимаешь тему, которую только что рассказал.

А как насчёт такого предложения: что, если мы используем свой «ум», чтобы просто писать STUPID-код. Код, настолько STUPID, что если бы компилятор мог генерировать эмоции, то вы бы увидели слёзы, льющиеся с монитора, а колонки воспроизвели бы звук громких аплодисментов. [Прим. пер.: stupid в переводе с английского — «глупый».]

Так что же я вам предлагаю? Что это за STUPID?

Ну, это довольно просто. Первая буква и расшифровывается как simple [«простой»].

▍ S расшифровывается как SIMPLE

Какое-то время назад я написал статью «Замедлитесь. Выполняйте задачи быстрее». В ней я рассказал о важности замедления для лучшего понимания того, что вы делаете. Если достаточно замедлиться, то можно достичь своей цели не только быстрее (потому что вам не придётся откатываться назад или вносить ненужные изменения), но и проще.

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

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

По сути, нужно поддерживать простоту кода, избегая «необходимости» добавления неожиданной сложности и увеличения технического долга без веской причины.

Помните популярную аббревиатуру KISS? Keep it simple, STUPID.

▍ T означает TESTABLE («тестируемый»)

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

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

Хотите быть адаптируемым? Пишите тесты. Без тестов вы можете считать, что движетесь быстро, но это заблуждение. Или вы движетесь быстро, но в обратном направлении, или вы будете двигаться быстро, но потом столкнётесь с преградой, которая доставит вам больше неприятностей, чем простой откат назад.

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

▍ U означает Ubiquitous («повсеместный»)

Эта идея была изложена Эриком Эвансом в его новаторской книге «Domain-Driven Design: Tackling Complexity in the Heart of Software». Это один из моих любимых аспектов, которые необходимо учитывать при программировании.

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

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

Какой бы объект вы ни создавали в своей кодовой базе, убедитесь, что он или минимизирует, или, что ещё лучше, полностью устраняет нюансы и неоднозначность, которые могут возникнуть у читающего код. Помните, что вы пишете код не для удобства компилятора, компилятор не позвонит вам посреди ночи, чтобы рассказать, насколько великолепен ваш код. С другой стороны, вам может позвонить коллега во время его ночного дежурства, чтобы задать вопрос, зачем вы добавили объект X, имеющий в кодовой базе то же самое значение, что и объект Y, но без понимания побочных эффектов X.

Это неожиданная сложность, и она очень неприятна.

Предпринимайте усилия к тому, чтобы сохранять во всей кодовой базе один язык. Если вы выберете язык предметной области, тем лучше. При обсуждении X с клиентом убедитесь, что это тот самый X, который присутствует в коде. Чётко и осознанно именуйте объекты (классы, методы, свойства, типы, модули и так далее.)

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

▍ P означает Proper («чистый»)

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

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

Баланс этой пользы всегда должен быть положительным.

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

Недавно на работе один и тот же разработчик писал мне во время пул-реквеста одни и те же комментарии: "Код плохо отформатирован. После фигурной скобки должно быть два пробела."

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

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

▍ I означает Incremental («инкрементный»)

Однажды я услышал фразу Кента Бека, запечатлевшуюся в моей памяти:

Заставь это работать. Сделай это правильно. Сделай это быстрым.

Недавно я дал себе разрешение добавить в этот список ещё один пункт.

 

 

Сделай это лучше.

 

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

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

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

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

Не спешите.

Двигайтесь медленно, чтобы завершать быстрее.

▍ D означает Decoupled («несвязный»)

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

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

Отвязывайте зависимости от системы. В прошлом я освоил архитектурный шаблон Entity-Control-Boundary, основанный на гексагональной архитектуре.

Мне он нравится.

Настолько сильно, что при помощи этой методики я разработал Cloudgenda. Я соло-разработчик этого SaaS-проекта и уверен, что могу быстро и непрерывно повышать ценность системы для клиентов благодаря тому, что ни одна из зависимостей не связана напрямую с внешними сервисами. На самом деле, каждая зависимость открыта и обрабатывается через объект Port and Adapter и реализуется с инъецированием зависимостей через конфигурацию. Благодаря этому, я могу очень легко тестировать свою кодовую базу и при желании рефакторить. К тому же с ней приятно работать.

Всё это рука об руку идёт с буквой D из принципов SOLID, которая расшифровывается как Dependency Inversion Principle (принцип инверсии зависимостей). Но этот принцип также можно применить к изолированию таблиц баз данных при их денормализации. Или когда вы правильно используете парадигму объектно-ориентированности, выбирая в некоторых случаях композицию вместо наследования. Мы можем назвать это «логическим изолированием», но преимущества этого такие же, как и при «физическом изолировании».

▍ В заключение

На моих часах уже 23:30, и я уже достаточно устал, чтобы идти спать.

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

Именно она замедляет вас, когда вы пытаетесь двигаться быстро. Именно она толкает вас вниз, когда вы стремитесь ввысь. Именно она заставляет вас смотреть вакансии в LinkedIn, когда вы готовы отказаться от работы над кодовой базой на текущем месте работы. Возможно, стоит дать себе шанс… а ещё лучше, дать шанс STUPID.

Возможно, однажды вы будете рассказывать на конференции о методике STUPID. И если это произойдёт, я, наверно, буду там в этой футболке, потому что знаю, что она работает.

I'm with STUPID

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

Похожее
19 мая
Автор: Сергей Спорышев
После весны 2020 года слово “тестирование” приобрело некоторые неожиданные значения и неоднозначные коннотации — пожалуй, везде, кроме IT. В нашей сфере без него никуда — и так было всегда. Видов тестирования ПО — множество: модульное, функциональное, А/В-тестирование, интеграционное, нагрузочное и...
24 марта
Автор: AnimeSlave
Я столкнулся с тем, что я иногда не понимаю код, с которым мне приходится работать. И это сильно сказывается на моей производительности и на качестве конечного результата. Неделю назад я прочитал статью «Плохо девелопмент» за авторством @dalerank (Сергей Кушниренко), в...
17 апреля
Рассмотрим интересную задачу по разработке игры «Крестики Нолики» на языке C#. Наш проект будет запускаться в консоли и потребует креативное мышление для решения задачи.  Ваша задача — реализовать консольную игру "крестики-нолики" с использованием языка программирования C#. Вам нужно создать игровое...
24 марта
Автор: Олег Борисенков
Рассказываем какие существуют стили именования переменных и зачем они нужны. Чтобы обеспечить легкую читаемость кода программисты используют разные стили именования для разных типов объектов, функций и переменных. Именно поэтому нет какого-то одного «идеального» формата. Выбор уместного стиля поможет быстро понять...
Написать сообщение
Тип
Почта
Имя
*Сообщение
RSS
Если вам понравился этот сайт и вы хотите меня поддержать, вы можете
Performance review, ачивки и погоня за повышением грейда — что может причинить боль сотруднику IT-компании?
Soft skills: 18 самых важных навыков, которыми должен владеть каждый работник
GraphQL решает кучу проблем — рассказываем, за что мы его любим
Разбираемся с middleware в ASP.NET Core
Как избавиться от прокрастинации до того, как она разрушит вашу карьеру
Функции и хранимые процедуры в PostgreSQL: зачем нужны и как применять в реальных примерах
Разрабы работают медленно и дорого — и люди считают нас лентяями. Просто в разработке всё сложно
Using a сustom PagedList class for Generic Pagination in .NET Core
Четыре типажа программистов
Интернет вещей — а что это?
LinkedIn: Sergey Drozdov
Boosty
Donate to support the project
GitHub account
GitHub profile