Статьи

Развитие, основанное на стыде

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

У нас есть несколько архаичных модульных тестов, написанных с использованием Easy Mock ; все наши более поздние юнит-тесты используют JMock . Эта небольшая часть технического долга означает, что если вы меняете код, где единственным охватом являются тесты Easy Mock, вам сначала нужно решить: исправляете ли вы тесты или, можете ли вы держать нос и жить / подправить существующий тест для ваши цели? Это не только отвлекает, но и означает, что делать правильные вещи можно значительно медленнее.
Изменение наших тестов Easy Mock на JMock, в принципе, является относительно простой задачей. Easy Mock объявляет издевательства простым способом:

1
private PricesService prices = createMock(PricesService.class);

Их можно легко преобразовать в стиль JMock:

1
2
3
private Mockery context = new Mockery();
...
private final PricesService prices = context.mock(PricesService.class);

EasyMock имеет несколько иной способ объявления ожиданий:

1
2
3
prices.prefetchFor(asset);
expect(prices.for(asset)).andReturn(
    Lists.newListOf("1.45", "34.74"));

Они должны быть переведены в ожидания JMock:

1
2
3
4
5
context.checking(new Expectations() {{
    allowing(prices).prefetchFor(asset);
    allowing(prices).for(asset);
        will(returnValue(Lists.newListOf("1.45", "34.74")));
}});

Этот процесс довольно механический, поэтому в течение 10% времени я начал использовать свой скриптовый инструмент рефакторинга — Rescripter — для механического перевода наших тестов EasyMock в JMock. Rescripter позволяет вам запускать код, который изменяет ваш исходный код Java. Но это больше, чем просто поиск и замена или регулярные выражения: используя мощный синтаксический анализ синтаксического дерева Eclipse, вы получаете доступ к полностью проанализированному представлению вашего исходного файла — это означает, что вы можете найти ссылки на методы, найти вызовы методов, имена, параметры списки и т. д. Это именно то, что вам нужно, учитывая характер перевода из одной библиотеки в другую.

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

После нескольких дней, проведенных на 10%, мне удалось собрать что-то потрясающее: я перевел пару сотен модульных тестов; но это было сделано с помощью 700 строк самого гротескного кода, на который вы когда-либо имели несчастье смотреть!
А потом … а потом на прошлой неделе у меня появился партнер по паре на день. Он должен был поделиться этим ужасом. Потратив 10 минут, объясняя ему проблему, а затем 15 минут, объясняя, почему это был одноразовый, одноразовый код, поэтому не было никаких модульных тестов. Я был смущен.
Мы начали пытаться внести небольшие изменения; но без тестовой структуры было трудно быть уверенным, что то, что мы делаем, сработает. Что еще хуже, нам нужно было изменить основные функции, используемые во многих местах. Это заставило меня нервничать, потому что не было тестового покрытия — поэтому мы не могли быть уверены, что не сломаем то, что уже было.
Честно говоря, это был абсолютный кошмар. Я так привык иметь тестовое покрытие и писать тесты — мысль о написании кода без юнит-тестов выводит меня из себя. Но здесь я был, с беспорядком непроверенного кода, полностью моего собственного создания. Почему? Потому что я простил себя за то, что «не делал все правильно». В конце концов, это только одноразовый код, не так ли? Это исследовательский, скорее всплеск, чем производственный код. Во всяком случае, после того, как все будет сделано и тесты перенесены, этот код будет бесполезен — так зачем делать его красивым? Я просто продолжу взламывать …
Удивительно, насколько разумно все это звучит. До тех пор, пока вы не поймете, что вы полный и полный блядь. Даже если это одноразовый код, даже если он имеет относительно короткий срок годности

Единственный способ идти быстро, это идти хорошо

Поэтому я сделал то, что сделал бы любой разумный человек. Я провел свой обеденный час, исправляя это положение вещей. Конечный результат? Теперь я могу написать модульные тесты в Jasmine, чтобы проверить рефакторинг, который я писал.
Мало того, что теперь я могу правильно протестировать новый код диска. Я мог бы написать тесты, чтобы покрыть мой существующий унаследованный код, чтобы я мог правильно его реорганизовать. Удивительно. И внезапно темпы прогресса подскочили. Вместо долгих циклов отладки и попыток вручную найти и запустить тестовые сценарии у меня был простой в использовании, повторяемый, автоматизированный набор тестов, который давал мне уверенность в том, что я делал.

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

Ссылки: Разработка, основанная на позоре, от нашего партнера JCG Дэвида Грина в блоге Actively Lazy .