Просмотров: 2559 шт.
Ваш код – отстой, если он не работает
Работает ли ваш код? С чего вы это взяли? Можете ли вы это доказать?
Если ваш код не имеет тестов, он – отстой. Я имею в виду – всесторонние, в достаточной мере детализированные программные тесты (известные также как Юнит-тесты (unit tests)), а также более высокоуровневые функциональные (functional) и интеграционные (integration) тесты. Тесты, которые автоматизированы. Тесты, которые запускаются постоянно. Включая программные тесты, запускающиеся после всякого изменения кода.
*****
Без адекватных тестов (подразумевая – как по количеству, так и по качеству), вы просто не можете иметь уверенность в том, что ваш код работает как нужно. Задумайтесь: даже если вы сами уверены в том, что вы сделали... почему кто-то еще должен слепо верить этому? А что вы скажете о людях, которые будут работать с вашим кодом в будущем и изменять его? Как они будут знать, что ваш код работает после изменений, выполненных позже?
Ваш код – отстой, если он не поддается тестированию
Отлично, вы решили добавить тесты в ваш код. Чаще всего, это не так-то просто. Скорее всего, ваш код просто-напросто не был спроектирован и/или реализован так, чтобы его было легко тестировать. Это означает, что вам придётся делать изменения в нём, чтобы сделать его поддающимся тестированию... не разрушив никакой функциональности (собственно это в наше время и называется рефакторингом (refactoring)). Но, выполняя такие изменения, можно ли быстро и уверенно сказать, что вы ничего не сломали в работающем коде, если в нём не было всесторонних и детализированных тестов? Вряд ли. (Похоже на задачку про курицу и яйцо – прим. перев.)
На самом деле, дела обстоят ещё хуже. Если вы принимаете решение о том, что вы будете писать тесты для всего своего кода после того, как написан сам код, вам придется приложить дополнительное усилие для того, чтобы передизайнить/переписать этот код с тем, чтобы сделать его тестируемым.
Сохранение адекватного уровня тестирования при подходе, когда тесты пишутся после самого кода, требует времени и планирования. И если вам приходится делать дополнительную работу для того, чтобы сделать код тестируемым... хм... этот код – отстой.
Написание тестов прежде написания самого кода означает, что код по определению поддаётся тестированию. Если вы отрабатываете тесты поочерёдно, вы получаете ещё больший выигрыш, поскольку каждый тест требует только инкрементальных изменений в коде, который уже проверенно работает.
Ваш код – отстой, если его трудно прочесть
Код должен быть легко читаем. Стив МакКоннелл (Steve McConnell) сказал в своём выступлении на SD West '04: код должен удобно читаться, а не удобно писаться.
Здесь следует отметить несколько факторов. Выбор хороших, говорящих сами за себя, имён – хорошее начало. Стремитесь к простым решениям, даже если они кажутся более многословными или неэффективными. Является ли эффективность проблемой, станет известно только впоследствии, при профилировании проекта в реальной ситуации использования продукта.
Выбирайте стиль и соглашения о форматировании на ранней стадии проекта, и следуйте этим соглашениям. Требуйте от других следования им же. Это будет легче сделать, если каждый внесёт свою лепту в такое соглашение. Всё это сделает ваш код единообразным и более лёгким в прочтении.
И избавляйтесь от дублирования кода во всех его проявлениях. Более подробно об этом – ниже.
Ваш код – отстой, если он непонятен
Этот пункт весьма близок к предыдущему. Код может быть читабельным, но, тем не менее, труднопонимаемым. Возможно, он читается хорошо, но вводит читающего в заблуждение. Представьте: вы потратили много времени, чтобы выбрать хорошее имя переменной, но способ её использования и её значение изменились в то время, как имя осталось прежним. Это ещё хуже, чем зашифрованное имя... по крайней мере, в последнем случае, читатель знал бы, что имя бессмысленно. Но если же имя не отражает сути, читатель будет иметь беспочвенные суждения о том, что происходит в коде, что в итоге приведёт к непониманию, и в конце концов – к багам.
Ваш код – отстой, если он догматично следует ультрамодным framework ценою соблюдения хороших практик дизайна и имплементации
Например, Боб Мартин (Bob Martin) недавно поднял вопрос о догматическом использовании private полей и getters/setters для простой структуры данных (например, Data Transfer Object – DTO). Если поле прозрачно для чтения/записи, почему бы просто не сделать поле public? В большинстве языков это возможно. Конечно, в некоторых – нельзя. Например, традиционно в Smalltalk все поля (fields) являются private, а все методы – public.
Обычно хорошо, если вы можете выбросить какой-то фрагмент из кода или избежать его написания. Использование тяжёлого framework обычно требует того, чтобы вы писали значительную часть кода, который попросту не имеет никакой ценности с точки зрения бизнеса (business value).
Есть множество разнообразных лёгких frameworks для Java. Они являются ответом на тяжёлые frameworks (такие как EJB), которые в последнее время фактически стали догмой. У O'Reilly есть книга об этом, в соавторстве с Брюсом Тейтом (Bruce Tate).
Когда вы выбираете framework, предпочтите более лёгкий framework, который будет делать всю необходимую работу. Использование средств типа Hibernate, Prevayler, Spring, PicoContainer, NakedObjects, и т. д., может действительно быть выигрышным во многих случаях. Никогда не принимайте слепо тяжёлый framework только потому, что это модно сегодня. Хотя также слепо не следует выбирать и лёгкий framework. Всегда взвешивайте прежде, чем принять решение.
Ваш код – отстой, если в нём есть дублирование
Дублирование – скорее всего, единственная, самая значительная вещь, которую нужно искоренить в вашем коде.
Дублирование имеет несколько форм:
текстовое
Оно – самое простое и легко находимое. Когда у вас есть секции кода, которые идентичны или очень похожи. Чаще всего – это результат программирования методом copy & paste. Есть несколько способов избежать этого вида дублирования, включая: выделение методов (extracting methods) и повторное их использование (reusing), превращение метода в шаблонный метод (template method), вынос его в суперкласс (superclass) и предоставления вариантов в подклассах (subclasses), и другие базовые виды рефакторинга. Подробности см. в книге «Рефакторинг» Мартина Фаулера (Fowler's "Refactoring").
функциональное
Это – особый вид текстового дублирования, когда у вас есть различные функции/методы, которые предназначены для одного и того же. Его можно часто встретить в проектах, которые разделены между группами разработчиков, недостаточно хорошо взаимодействующих друг с другом. Также, оно может быть результатом copy & paste, или просто незнания существующего кода или библиотек. Практики и полиси (practices and policies), которые стимулируют и способствуют знанию всего объёма кода и всех библиотек и frameworks, находящихся в использовании, позволяют избежать функционального дублирования.
временное
Оно – немного более трудное, менее ясное, и не так легко обнаруживаемое. У вас есть временное дублирование, когда одна и та же работа делается повторно – в то время, когда так не должно быть. Это не проблема в том же понимании, как предыдущие две формы дублирования, так как это не приводит к наличию лишнего кода. Но это может стать проблемой при масштабировании системы, когда повторяющаяся работа начинает отнимать много времени. Для решения этой проблемы могут использоваться различные техники кеширования.
Из трёх вышеназванных типов, текстовое дублирование является самым худшим. Оно загрызёт вас раньше других, когда ваша система будет расти. Оно имеет гадкую особенность быть подобной вирусу: когда ваш код заболел дублированием, он уговаривает вас думать: "О, это не такая уж и проблема, если я просто возьму вот этот кусок кода, положу его копию здесь и немного подгоню его. В конце концов, все вокруг делают это!" Это сильно напоминает Разбитое Окно (Broken Window), о котором говорили Дэйв Томас и Энди Хант (Dave Thomas & Andy Hunt). Если вы не возвыситесь над мелочами, которые появляются так или иначе, всё в конце концов пойдёт коту под хвост.
Итог
Итак, весьма вероятно, что какая-то часть вашего кода – отстой.
Что с этим можно сделать? Ну, для начала вам придётся признать факт (и я надеюсь, что эта статья вам помогла в этом) и сознаться в том, что это – проблема.
Затем, у вас есть выбор. Вы можете что-то с этим делать. Вы можете изучить новые способы работать: способы, которые помогут вам писать лучший код. Вот и чудесно. Если хотя бы один программист здесь делает это, я буду счастлив.
Ваш второй вариант – не делать с этим ничего, и продолжать писать код так же, как прежде.
Это ваш выбор. Выбирайте с умом.