Астрологи обьявили неделю Тестируемого Кода.

Простота поддержки приложений выросла дофига.

Никогда не будет лишним напнить себе о принципах тестируемого кода. Под “тестируемым кодом” будем понимать код, который можно легко покрыть unit-тестами. Само по себе определение unit-теста дискусионно (об этом в другой раз). Сейчас будем считать что unit-тесты — это тесты которые для своего выполнения не нуждаются в меж-процессных взаимодействиях (обращениях к БД, сети, файловой системе и т.д.).

Даже если мы не пишем unit-тесты (почти) никогда, уже само по себе следование принципам тестируемости улучшает качество и простоту поддержки кода. К тому же, всегда есть небольшая вероятность что время для написания тестов появится (хаха), и вы (или кто-то другой) будете благодарны себе за то что для покрытия проекта тестами его не нужно переписывать “с нуля”.

Можно сказать что “тестируемость кода“ - это отсутствие факторов которые затрудняют написание unit-тестов.

Пожалуй основной принцип тестируемости - изоляция кода бизнес-логики от меж-процессных взаимодействий (инфраструктурного кода). Замечу что имеет смысл покрывать unit-тестами именно код бизнес-логики. Инфраструктурный код тестируется в рамках интеграционных тестов, и следовательно к нему эти принципы применять не обязательно.

Код бизнес-логики - это код где принимаются решения, и который оперирует высокоуровневыми понятиями (”пользователь”, “заявка”, “документ”). Этот код - самый ценный для компании, он главный артефакт нашей работы.

А инфраструктурный код - это весь остальной вспомогательный код, который обеспечивает работу с сетью, БД, файлами и т.д. Он оперирует низкоуровневыми понятиями (”файл”, “таблица”, “POST-запрос”). Этот код не явлеется ключевой ценностью для компании и может быть заменен другой реализацией при необходимости. Все фреймворки, ORM и большинство библиотек в vendor принадлежат целиком к этому типу кода.

Когда в процессе написания бизнес-кода задаешься вопросом “а как это можно было бы покрыть unit-тестом?”, невольно будешь вынужден отделять его от инфраструктурного кода. Кстати, главная задача правильной архитектуры - обеспечить это разделение и сделать так чтоб инфраструктурный код зависел от кода бизнес-логики, но не наоборот (об этом тоже в другой раз).

Также, думая о unit-тестах, с большей вероятностью будешь применять SOLID и разбивать программу на компоненты с низким зацеплением и высокой связностью (low coupling, high cohesion).

Кроме этого фактора есть множество менее критичных. Краткий список есть в этой статье от разработчиков в Гугле http://misko.hevery.com/code-reviewers-guide/, а из нее можно перейти к более подробным статьям с обоснованиями. Но там много читать не по-нашому, так что я сам еще всё не прочёл) Но хотя бы поверхностно рекоммендую просмотреть.