Рефакторинг JAVA с использованием отражения

Я использую сторонний API в нескольких приложениях Java. Они обновили несколько вещей в последней версии. Нам придется обновиться до последней версии, и для этого потребуются соответствующие изменения в нашем коде. Изменения,

1) Интерфейс и имя абстрактного класса, которые мы использовали для реализации/расширения, были изменены. Кроме того, имена методов были изменены. Это все просто изменения названия.

2) Необходимо аннотировать класс, реализующий эти интерфейсы, с помощью @Service

3) Затем нужно добавить новый файл Java и файл свойств.

4) У нас также есть абстрактный класс, который реализует абстрактный класс третьей части, а затем есть много конкретных классов. Таким образом, несколько методов из стороннего абстрактного класса были переопределены в нашем базовом абстрактном классе, который расширяет базовый абстрактный класс, и несколько методов присутствуют в конкретном абстрактном классе.

Я могу выполнить рефакторинг через Eclipse IDE, но мы этого не предпочитаем. Мне нравится, чтобы это было полностью автоматизировано, как запуск скрипта.

Я попытался с отражением Java найти весь конкретный класс абстрактного класса и переименовать методы. Тем не менее, это выглядит рискованно.

Есть ли другой лучший подход?


person user1578872    schedule 26.09.2016    source источник
comment
Пожалуйста, будьте более конкретными   -  person JnRouvignac    schedule 27.09.2016
comment
«Интерфейс и имя абстрактного класса, которые мы использовали для реализации/расширения, были изменены. Кроме того, имена методов были изменены». По этой причине я бы подумал о сбросе или замене этой библиотеки, если у вас есть такая возможность.   -  person VGR    schedule 27.09.2016


Ответы (3)


Это зависит от того, сколько кода вам нужно изменить, сколько времени уходит на выполнение каждого шага и сколько раз вы повторяете один и тот же рефакторинг. Если это всего лишь несколько сотен классов и/или более простые рефакторинги, такие как переименование класса/интерфейса, могут выполнить большую часть работы, тогда делайте это вручную.

В противном случае, если вы действительно хотите, вы можете попробовать написать правила в таком инструменте, как AutoRefactor: https://github.com/JnRouvignac/AutoRefactor

Отказ от ответственности: я являюсь автором AutoRefactor.

person JnRouvignac    schedule 26.09.2016

Помнится, я где-то читал, что программист — это тот, кто скорее потратит 12 часов на написание сценария для автоматизации ручной задачи, чем потратит 20 минут на ее выполнение.

Я понимаю, почему вы хотите автоматизировать это — используемый вами API усложняет жизнь своим клиентам, переименовывая вещи. Для API необычно нарушать совместимость только с именами - вы уверены, что это так просто?

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

person Neville Kuyt    schedule 27.09.2016

К сожалению, я не знаю сейчас точных деталей вашей ситуации. Я могу указать некоторые принципы, которые могут упростить жизнь в будущем, согласно моему опыту.

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

Таким образом, в случае изменения стороннего кода вы будете вносить изменения только в одном месте. Этот подход дает вам дополнительную свободу: если вы решите использовать другой сторонний API, это будет просто, потому что основная часть вашего кода не будет затронута. Также это полезно при тестировании: вы можете сымитировать реальный сторонний функционал.

Например, предположим, что вашему проекту необходимо постоянное хранилище. Итак, вы можете начать с объявления интерфейса следующим образом:

interface IStorage {
    void save(Model m);
    Model load(int id);
}

Это позволит вам:

  • Примите решение о поставщике хранилища (это может быть MySQL или MongoDB или просто XML-файл на диске) позже.
  • Легко замените один сторонний API другим (например, перейдите с хранилища файлов на БД).
  • Легко протестируйте свою бизнес-логику, смоделировав этот интерфейс вместо использования реального хранилища.
  • Ускорить разработку, если некоторым модулям (которые должны делать другие разработчики) требуется рабочее хранилище (они просто будут использовать IStorage интерфейс, как будто он уже реализован).
person Community    schedule 26.09.2016