Ищу предложения по редизайну интерфейса - PullRequest
0 голосов
/ 03 июня 2010

В рамках поддержки большого фрагмента унаследованного кода нам необходимо изменить часть проекта в основном, чтобы сделать его более тестируемым (модульное тестирование).Одна из проблем, которую нам нужно решить, - это существующий интерфейс между компонентами.Интерфейс между двумя компонентами - это класс, который содержит только статические методы.

Упрощенный пример:

class ABInterface {

    static methodA();
    static methodB();
    ...
    static methodZ();
};

Интерфейс используется компонентом A, поэтому различные методы могут использовать ABInterface :: methodA () для подготовки некоторых входных данных и последующего вызова соответствующих функций вкомпонент B.

Сейчас мы пытаемся изменить интерфейс по разным причинам:

  • Расширение покрытия модульных тестов - нам необходимо устранить эту зависимость между компонентами и заглушками/ mocks должны быть введены

  • Интерфейс между этими компонентами отличается от оригинального дизайна (т. е. множество новых функций, используемых для межкомпонентного i / f, создаются вне этогоинтерфейсный класс).

  • Код устарел, со временем сильно изменился и нуждается в рефакторинге.

Изменение не должно нарушать работу остальной системы.Мы пытаемся ограничить оставление многих необходимых для тестирования артефактов в производственном коде.Производительность очень важна и не должна (или очень минимально) ухудшаться после перепроектирования.Код OO в C ++.

Я ищу несколько идей, какой подход выбрать.Любые предложения о том, как сделать это эффективно?

Ответы [ 3 ]

1 голос
/ 05 июня 2010

Самый простой ответ - обернуть старую библиотеку, которая имеет статический интерфейс в фасаде, а затем реорганизовать код для вызова нового фасада вместо старой библиотеки. Этот новый клин должен позволять замену библиотеки для целей модульного тестирования. Сначала проверьте его на одном методе, просто чтобы увидеть, как его реализовать.

Что меня действительно беспокоит, так это когда вопрос заражен «проблемами производительности». Мы все написали критически важный для производительности код, и никто никогда не предлагал писать плохо работающий код. Я нахожу, что эти "проблемы" обычно исходят от скептиков, которые осуждают каждое изменение, и на самом деле не имеют ни малейшего понятия, почему определенное изменение будет или не будет работать хорошо. Помните, что единственное достоверное доказательство производительности исходит от тестирования. Запустите тест производительности и установите базовый уровень. Внесите свои изменения. Запустите ваши тесты производительности снова в новом коде. Продемонстрировать фактическое влияние. Только тогда вы сможете принять решение относительно фактического воздействия изменений. Вы не должны никогда позволять придиркам в течение циклов доминировать в ваших проектах, пока не будет продемонстрировано иное.

Звучит так, будто кто-то важный в вашем проекте - старый программист на Си *, который давно слышал, как кто-то говорит "что-то вроде" единственный способ заставить C ++ работать быстро, это использовать статические методы ". Проблема в том, что он все еще верит в это. Двадцать лет назад, возможно, прав был, но компиляторы и оптимизаторы значительно улучшились за эти два десятилетия. Так что попробуйте свои изменения.

Скорее всего, если вы используете современный компилятор, оптимизатор все равно удалит лишние разыменования в объектном коде, что означает, что вы вообще не добавили никакого воздействия во время выполнения.

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

  • Примечание: я также старый программист на Си, который также говорил такие глупости 20 лет назад. Разница в том, что я узнал, что некоторые оптимизации гораздо более важны, чем другие, и что новые компиляторы удивительно хороши в вычислении большинства вещей самостоятельно. Мои попытки преждевременно «оптимизировать» вещи обычно заканчивались дорогостоящим в обслуживании кодом, который, как правило, в любом случае не превосходит настройки стандартного компилятора.
0 голосов
/ 04 июня 2010

Спасибо за ответы и комментарии.

После ознакомления с главой «Методы разрушения зависимостей» из книги Эффективная работа с устаревшим кодом комбинация следующих двух методик фактически является решением нашей проблемы:

  • Instance Delegator - чтобы обернуть / заменить статические методы из служебного класса новыми виртуальными методами.
  • Static Setter - чтобы включить создание экземпляров другой утилитыкласс (либо рабочий код, либо код заглушки).

Сочетание этих двух позволит нам отделить тестируемый компонент от остальной части кода продукта.

Нашей единственной заботой сейчас является снижение производительности (из-за использования виртуальных функций).

0 голосов
/ 03 июня 2010

Если бы методы A-Z были нестатичными и виртуальными, вы могли бы сделать это легко, правильно? Таким образом, если бы статический метод A-Z вызывал нестатический, виртуальный метод A-Z, вы могли бы переопределить поведение. Зная это, вам нужен способ изменить экземпляр, содержащий нестатические версии для тестирования.

В качестве альтернативы, вы можете взять два класса, которые вы хотите реорганизовать, и заставить их использовать оболочку для этого статического класса. Тогда они могут расходиться столько, сколько нужно.

Это все мои идеи, не смотря на реальную проблему.

...