С уважением, прекрасный ответ Карла Манастера, есть некоторые недостатки, которые вы должны хотя бы рассмотреть перед тем, как отправиться на путь, предложенный Карлом.
Наиболее важным из них является следующее: мы используем инкапсуляцию, чтобы минимизировать количество потенциальных зависимостей, которые несут наибольшую вероятность распространения изменений. В вашем случае у вас есть инкапсулированные частные методы внутри вашего класса: они недоступны для других классов и, следовательно, нет никаких потенциальных зависимостей от них: стоимость любых изменений, которые вы им делаете, сводится к минимуму и имеет низкую вероятность распространения на другие классы.
Кажется, что Карл предлагает переместить некоторые частные методы из вашего класса в новый класс и сделать эти методы общедоступными (чтобы вы могли их протестировать). (Кстати, почему бы просто не сделать их общедоступными в первоначальном классе?)
Делая это, вы удаляете барьер на зависимости от других классов, создавая зависимости от этих методов, что потенциально увеличивает стоимость использования этих методов, если любые другие класс возьмутся за их использование.
Вы можете судить об этом незначительном несовершеннолетнем и стоящей цене, чтобы заплатить за возможность проверить ваши личные методы, но, по крайней мере, знать об этом. В небольшом числе случаев это может быть действительно полезно, но если вы внедряете это во всей своей кодовой базе, вы резко увеличите вероятность того, что эти зависимости сформируются, увеличив стоимость вашего цикла обслуживания до неизвестной степени.
По этим причинам, я не согласен с Карлом, что его предложение,»... отличный пример того, как TDD улучшает дизайн.»
Кроме того, он утверждает, «В оригинальном классе, что постороннее функциональность ушел , завернутый в проросший класс, поэтому дизайн первоначального класса проще и лучше соответствует принципу единой ответственности.
Я бы сказал, что перемещаемая функциональность вовсе не «Внешняя.«Кроме того,« Упрощенный »не является четко определенным: конечно, может быть, что простота класса обратно пропорциональна его размеру, но это не значит, что система простейших возможных классов будет самой простой возможной системой: если бы это было так, все классы содержали бы только один метод, и система имела бы огромное количество классов; удаление этого иерархического слоя из нескольких методов внутри классов, можно утверждать, сделает систему намного сложнее.
Принцип единой ответственности (СРП), кроме того, является, как известно, субъективным и полностью зависит от уровня абстракции наблюдателя. Совсем не так, что удаление метода из класса автоматически улучшает его соответствие SRP. Класс принтера с 10 методами имеет единственную ответственность за печать на уровне абстракции класса. Одним из его методов может быть checkPrinterConnected(), и может быть checkPaper(); на уровне метода это явно отдельные обязанности, но они автоматически не предполагают, что класс должен быть разбит на другие классы.
Carl заканчивает: «В классе прорастания извлеченная функциональность - это его raison d'etre, поэтому для него является общедоступным, и поэтому он может быть проверен без тестовых изменений». Важность функциональности (это смысл, d'etre-ness) не является основанием для уместности его публичности. Основой для приемлемости публичности функциональности является минимизация интерфейса, открытого для клиента, так что функциональность класса доступна для использования, в то время как независимость клиента от реализации функциональности максимизируется. Конечно, если вы перемещаете только один метод в проросший класс, тогда он должен быть общедоступным. Однако, если вы перемещаете более одного метода, вы должны сделать эти методы общедоступными, что имеет важное значение для успешного использования клиентом класса: эти общедоступные методы могут быть гораздо менее важными, чем некоторые частные методы, из которых вы хотите защитить свои клиент. (В любом случае, я не поклонник этого, «Raison-d'etre», фраза как важность метода также не определена.)
Альтернативный подход к предложению Карла зависит от насколько велика ваша система для роста. Если он вырастет до менее чем нескольких тысяч классов, то вы можете подумать о том, чтобы сценарий скопировал исходный код в новый каталог, измените все события «private» на «public» в этом скопированном источнике, а затем напишите тесты против скопированного источника. Это имеет недостаток времени, необходимого для копирования кода, но преимущество сохранения инкапсуляции исходного источника, но при этом все методы проверяются в скопированной версии.
Ниже приведен сценарий, который я использую для этой цели.
С уважением,
Ed Кируон
!/Bin/Баш
гт -rf код-копия
эхо Создание кода ксерокопию ...
MkDir code- копия
cp -r ../www код-копия/
для i в find code-copy -name "*php" -follow
; сделать
sed -i 's/private/public/g' $i
сделали
PHP run_tests.PHP
Точно то, что мне было нужно. Класс sprout для меня новичок (также другие модели xunit). Спасибо alot – Hanseh
Хорошая книга для этого: ** Эффективная работа с устаревшим кодом. ** – Gutzofter