Как часто вы поражаетесь, читая чужой код, и думаете «господи, ну и каша...». Скорее всего, достаточно часто. И можете ли вы быть уверенным, что никто не думал также когда читал ваш код? Другими словами, насколько вы уверены в чистоте своего кода? Можно быть уверенным только если полностью понимаешь, что значит чистый код.


Сложно дать точное определение чистому коду, и, скорее всего, сколько программистов — столько определений. Однако, некоторые принципы достаточно универсальны. Я собрал девять самых релевантных и описал ниже.


1.Плохой код делает слишком много, чистый код сфокусирован


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


Но я бы не ограничивал определение классами. В свой последней статье Ральф Вестфал (Ralf Westphal) представил более широкое определение принципа единственной обязанности:


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


Если хотите узнать больше, то советую прочитать его статью.

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


Не язык делает программу простой, а программист, который делает так, что язык выглядит просто.

(цитата Роберта C. Мартина)


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


3. Не нужно избыточности


Код должен подчиняться правилу DRY (Don’t repeat yourself — не повторяйся). Если это так, то модификация любого элемента системы не требует изменения других, логически не связанных элементов.


4. Читать ваш код должно быть приятно


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


Для этого нужно стараться подчиняться принципам KISS (Keep It Simple, Stupid!) и YAGNI (You Ain’t Gonna Need It — Вам это не понадобится). Принцип KISS гласит, что большинство систем работают лучше всего если сохранять их простоту, а не развивать сложность.


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


5. Другой разработчик может легко расширить ваш код


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


6. Нужно минимизировать зависимости


Чем больше зависимостей, тем сложнее поддерживать и изменять код в будущем. Всегда (в случае с .NET, — прим. пер.) можно помочь себе минимизировать зависимости с NDEPEND, например. Он проверяет потенциальные ошибки в зависимостях в коде.


7. Меньше — лучше


Код должен быть минимальным. Классы и модули должны быть короткими, в идеале — всего несколько строк кода. Код должен быть хорошо разделен (в том числе внутри класса). Чем лучше вы делите код, тем легче его читать. Этот принцип хорошо влияет на пункт 4 — другим программистам будет проще понять его.


8. Необходимы юнит- и приемочные тесты


Как можно узнать, удовлетворяет ли наш код требованиям, если не писать тесты? Как можно поддерживать и расширять его, не боясь, что все сломается? Код без тестов — просто не чист. Если хотите узнать больше о принципах юнит-тестирования, то советую прочитать очень хорошую статью Three Pillars of Unit Tests, написанную одним из моих коллег.


9. Код должен быть выразительным


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


Так что же такое чистый код?


В целом, одно последнее качестве можно назвать итогом всего вышесказанного:


Чистый код написан тем, кому не плевать.

цитата Майкла Фетерса (Michael Feathers).


Он написан тем, кто относится к коду как к искусству, и кто обращает внимание на все детали.


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

Поделиться с друзьями
-->

Комментарии (36)


  1. yury-dymov
    19.09.2016 13:04
    +26

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


  1. tmn4jq
    19.09.2016 13:17
    +1

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


    1. dendron
      19.09.2016 17:38
      +1

      Согласен. Лично у меня стек абстракций ограничен, где-то на 10-м уровне вложенности классов происходит его переполнение и я вообще перестаю понимать что этот код делает и зачем я сюда пришёл. Со всякими «крутыми штуками» вроде мета-программирования, функциональщины, абстрактных интерфейсов и шаблонов проектирования это происходит ещё быстрее.

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


  1. andreysmind
    19.09.2016 13:46
    +10

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

    В последнее время я очень часто наблюдаю как разработка тормозится потому, что команда разработчиков решает философские проблемы выразительности и оптимизации проекта на стадии Proof of Concept.


    1. Kukunin
      19.09.2016 14:17
      +3

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

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

      Код, который не развивается — мертвый код.


      1. andreysmind
        19.09.2016 14:48
        +4

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

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

        А что такое «будущие нужды» и как их определить?

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

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


        1. stokker
          20.09.2016 16:24

          Так Боб говорит о коде, а для стартапов важнее бизнес-процессы. Или, более точно, для стартапов чистота кода не является бизнес-требованием.


          1. andreysmind
            20.09.2016 16:33

            Совершенно верно. Но в стартапы приходят программисты(хорошие программисты, отличные умные ребята, без иронии), которые очень хорошо знают о чистоте кода, антипаттернах и лучших практиках. Поскольку обычно их не интересуют бизнес-процессы и схемы по которым деньги зарабатываются, то вместо выпуска продукта они начинают улучшать мир за счет инвесторов. Ну и результат становится легко предсказуемым.


            1. xuexi
              20.09.2016 16:34

              Бизнес == говнокод?


              1. andreysmind
                20.09.2016 16:50

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


                1. xuexi
                  20.09.2016 16:55

                  Ну в целом, так и получается, бизнес провоцирует написание говнокода. Бизнес => говнокод.


                  1. andreysmind
                    20.09.2016 17:28

                    Это утверждение справедливо, да.


                  1. stokker
                    23.09.2016 15:53

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


        1. 3aicheg
          20.09.2016 16:26

          А что такое «будущие нужды» и как их определить?


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

          если приложение не будет написано или будет написано с опозданием на год


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


      1. Idot
        19.09.2016 14:54

        Тот же дядька Боб заявлял, что выполнять свою работу для кода — это второстепенное качество.

        Если чистый код выполняется неприемлемо долго (например, красивый SQL запрос выполняется часами, вместо пары минут), то в пекло такой код!


    1. marcor
      19.09.2016 14:26
      +3

      Где-то в статье о геймдеве я прочитал хороший совет: «Писать прототипы, не обращая внимания на чистоту кода нормально, если после появляения убеждённости в том, что концепция работает, прототит будет выброшен. Вне зависимости от того, насколько он удовлетворяет заказчика».
      Абсолютно согласен с данным отношением к proof of concept: доказано — перепиши начисто.


      1. BulldozerBSG
        19.09.2016 17:58
        +1

        Совет хороший но больше является крайностью и из теории.
        На практике все получается несколько иначе.

        После написания прототипа будет два пути:
        1. Если прототип не устраивает в плане архитектуры (степень производительности и\или возможности расширения) то начинаем сначала: пишем прототип.
        2. Если все устраивает. то прототип проходит процедуру рефакторинга. Устраняются все FIXME, TODO (которые вы должны были оставлять по мере написания прототипа). В общем код доводится до продакшен состояния.


  1. nikolaikopernik
    19.09.2016 14:09
    +2

    Ваша статья одним словом: S.O.L.I.D.


  1. Idot
    19.09.2016 14:49

    На мужике с ножницами на картинке к статье женские туфли на каблуках? Или это женщина мужиковатого телосложения?


    1. marenkov
      19.09.2016 17:13

      Лагерфельд собственной персоной ;)


    1. Idot
      19.09.2016 17:45

      За что СТОЛЬКО минусов в Карму за столь нейтральный вопрос? Я же не сказал, что «носить женские туфли для мужчины неприемлемо», с чего все минусующие решили, что я не толерантен к кросс-дрессерам?
      (кросс-дрессер — не обязательно гей: он может быть и «лесбиян» сексующийся с девушками надев женское платье;
      а гей — не обязательно кросс-дрессер, он может быть и огромным бородатым волосатым мужиком с большими бицепсами любящего других мужчин)

      PS с обвинениями в провокации — тоже не ко мне, а к автору статьи!
      Не я эту картинку сюда поместил!


    1. Chamie
      20.09.2016 12:17

      Если вы про жёлтую вертикальную полоску сзади:

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


  1. xuexi
    19.09.2016 14:59
    +4

    Без наличия общей формализованной модели понятий (онтологии) для всех участников индустрии подобные статьи это просто трата байтов. Сродни Библии или Корану, просто слегка знакомые всем вокруг слова, выстроенные в предложения таким образом, чтобы создавать иллюзию глубокой осмысленности. Аспекты, простота, чистота. Аминь.


  1. kirill3333
    19.09.2016 17:51

    freetonik подписан на вас очень нравятся статьи и переводы, но вот эта статья она кому адресована? если джуниорам то им без примеров тяжело рассуждать о высоких таких материях, а тем у кого опыта побольше уже и сами пришли к этим выводам


    1. MeGaPk
      20.09.2016 08:55

      скоре всего, людям на уровне джуниоров и сениорах. На этом этапе. Скажем там, подкрепить свои мысли.


  1. Toshiro
    19.09.2016 18:26

    Мне гораздо больше понравилось вот это: «Пишите код, который легко удалять, а не дополнять» — https://habrahabr.ru/company/payonline/blog/277629/

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

    Тоесть… хммм… выстраивайте иерархию правил по уровню критичности, а не пытайтесь согласовать кашу с разных уровней абстракции.

    «Пристрели того парня, который пытается 5 яиц разложить в 3 корзины» (с) Black Lagoon


  1. AndreyRubankov
    20.09.2016 12:20

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

    К примеру, «3. Не нужно избыточности» и «6. Нужно минимизировать зависимости» противоречат друг другу.
    Первый гласит про DRY принцип, возводя его в абсолют мы получаем множество маленьких кусочков кода, тем самым увеличиваем количество зависимостей. Тот же модуль isArray в npm, с одной стороны хорошо мы не дублируем код, с другой стороны у нас появляется новая зависимость.


  1. G-M-A-X
    20.09.2016 14:46

    Использование фреймворков и ООП шаблонов нарушает многие пункты :)


    1. AndreyRubankov
      20.09.2016 15:47

      Тут дело не в шаблонах, скорее язык выбран не правильно; см. «2. Язык, на котором вы написали код, должен выглядеть как будто его создали для решения этой проблемы.»

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


      1. andreysmind
        20.09.2016 16:38

        Мне нужно нарисовать кнопку, которая при нажатии открывает новое окно. Это функциональная задача или ООП?


        1. AndreyRubankov
          20.09.2016 16:54

          Идеальный ответ: «Depends on...», — ведь может быть очень много дополнительных условий. К примеру на html это описывается одним тегом без какого-либо кода.

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


          1. andreysmind
            20.09.2016 17:07

            Вот об собственно этом я и говорю — не всегда стоит тратить время на рассуждение о парадигмах и концепциях.


            1. xuexi
              20.09.2016 17:15

              Потом на собеседовании тяжело будет.


  1. nicholas_k
    20.09.2016 16:23

    Макконнел и Мартин написали более объемно, но и более полезно.


  1. mrguardian
    20.09.2016 16:24

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


  1. kmmbvnr
    22.09.2016 06:06

    Когда пишете про DRY, надо всегда упоминать KISS и KISS впереди DRY

    А то иногда такого можно понаворотить, чтоб если что можно было одну строчку править, вместо двух.