Статьи

Комментарии к коду и гибкое программирование

PEOP0067

Давным-давно, в далекой галактике, мы были вынуждены называть переменные и методы с очень короткими именами. Когда я начинал свою карьеру, я программировал Clipper, а C. Clipper был компилятором dBase, поэтому для имен переменных у него было всего 10 символов. Вы можете написать более длинные имена переменных, если хотите, но только первые 10 имеют значение. Я думаю, что в то время С дал нам 32 символа. Но сейчас мы не так ограничены. Итак, аргумент гласит: если вы используете длинные имена переменных, вам не нужно комментировать свой код. Я так много спорил.

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

Иногда нужны комментарии

И все же я бы сказал, что бывают моменты, когда комментарии имеют смысл. Не столько за то, что ты сделал, но за объяснение, почему ты решил сделать это так, как сделал. Опять же, вы не всегда должны это делать. Но бывают случаи, когда я пишу свой код, смотрю на него и думаю: «Если я вернусь к этим трем месяцам спустя, я удивлюсь, о чем я думал. Я бы лучше добавил комментарий, чтобы прояснить, почему это утверждение здесь ».

Вы видите, почему мы это комментируем. Не то, что. Что будет описано в самом коде.

Идеальный мир

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

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

Требования вместо комментариев

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

Но нам все еще не хватает возможности связать код с этой функцией.

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

Тесты как комментарии

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

Так что, если у меня есть класс с именем Math, который имеет функцию Add:

namespace Math
{
    public class Math
    {
        public int Add(int a, int b)
        {
            return a + b;
        }
    }
}

Я мог бы иметь тестовый класс, который выглядит так:

namespace Math.Math.Add
{
   [TestFixture]
    public class GivenTwoPositiveNumberAsParameters
    {
        private _math;
        [SetUp]
        public void Setup()
        {
            _math = new Math();
        }

        [Test]
        [TestCase(1,1)]
        [TestCase(5,7)]
        public void ThenTheResultShouldBePositive(int a, int b)
        {
           Assert.That(_math.Add(a,b), Is.GreaterThan(0));
        }
    }
}

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

TDD как комментарии — история

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

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

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

Код Отзывы

Во время проверки кода следует поднять несколько вопросов:

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

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

Вывод

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