Еще одно важное правило, которое я хотел бы добавить, заключается в следующем:
Если вы чувствуете необходимость либо написать какой-то декартово произведение дел в ваших тестовых случаях, либо если вы хотите издеваться над некоторыми частными методами класса, единая ответственность нарушается.
У меня недавно было это следующим образом:
У меня было определенное абстрактное синтаксическое дерево сопрограммы, которое будет сгенерировано в C позже. А пока, думайте об узлах как последовательность, итерация и действие. Последовательность объединяет две сопрограммы, Итерация повторяет сопрограмму, пока пользовательское условие не станет истинным, и Действие не выполнит определенное пользовательское действие. Кроме того, можно аннотировать действия и итерации с помощью кодовых блоков, которые определяют действия и условия для оценки по мере продвижения сопрограммы.
Необходимо было применить определенное преобразование ко всем этим блокам кода (для тех, кто заинтересован: мне нужно было заменить концептуальные пользовательские переменные фактическими переменными реализации, чтобы предотвратить конфликты переменных. Те, кто знает макросы lisp, могут думать о gensym В бою :) ). Таким образом, самой простой вещью, которая работала бы, был посетитель, который знает операцию внутри и просто вызывает их в аннотированном кодовом блоке Action и Iteration при посещении и обходит все узлы синтаксического дерева. Однако в этом случае мне пришлось бы продублировать утверждение «преобразование применено» в моем тестовом коде для метода посещения и действия и метода посещения. Другими словами, мне пришлось проверять тесты продукта на наличие обязанностей Traversion (== {ход итерации, действие обхода, последовательность обхода}) x Преобразование (хорошо, преобразованный кодовый блок, который превратился в итерацию, преобразованную и преобразованное действие). Таким образом, у меня возникло желание использовать powermock, чтобы удалить метод преобразования и заменить его некоторым «return», я был преобразован! »; - Stub.
Однако, согласно практическому правилу, я разделил класс на класс TreeModifier, который содержит экземпляр NodeModifier, который предоставляет методы modifyIteration, modifySequence, modifyCodeblock и так далее. Таким образом, я мог легко проверить ответственность за обход, вызывая NodeModifier и реконструируя дерево, и тестировать фактическую модификацию блоков кода отдельно, тем самым устраняя необходимость в тестах продукта, потому что теперь обязанности были разделены (на обход и реконструкцию и конкретная модификация).
Интересно также отметить, что позже я мог бы многократно использовать TreeModifier в различных других преобразованиях. :)