Как реорганизовать идентификатор String в идентификатор класса в большом устаревшем проекте? - PullRequest
0 голосов
/ 06 декабря 2018

В этом большом устаревшем проекте есть базовый класс MyObject, у которого есть свойство ID, которое было закодировано как String.Этот идентификатор доступен повсюду в проекте.

public class MyObject {
  private String id;

  public String getId(){
    return id;
  }
}

Я смотрю на возможность рефакторинга этого свойства String для идентификатора класса типа с помощью следующих методов:

class Id implements Comparable<Id> {
  String value
  Id(String value)
  String getValue()
  int hashCode()
  boolean equals(Object obj)
  int compareTo(Id o)
  String toString()
}

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

  • Получение идентификатора объекта, сохранение его в переменной и последующее сравнение с ним
  • Создание списка или установка и добавление объектаИдентификаторы к нему или проверьте, содержится ли идентификатор уже (без пользовательских компараторов)
  • Сравните идентификатор объекта со строковым значением (например, пользовательским вводом), иногда с equals(), а иногда с equalsIgnoreCase()
  • Сравните два идентификатора объекта

В частности, я хотел бы сделать следующее:

  • Тип рефакторинга идентификатора от String до Id
  • Измените текущий метод String getId() на Id getUniqueID()
  • Если идентификатор сравнивается со строкой, напрямую использующей id.equals("String") или id.equalsIgnoreCase("String"), измените его на id.equals(new Id("String"))
  • Добавьте новыйметод (со старым именем) String getId(), который вернет getUniqueID().getValue().Это для обратной совместимости с кодом клиента, который опирается на старые идентификаторы String.

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

Я рассмотрел рефактор IDEA: функция переноса типа, но, похоже, это не так.в состоянии сделать это.Обычно я не работаю в IDEA, поэтому я могу делать что-то не так, но он говорит мне, что есть несколько сотен конфликтов, и список вещей, которые он не может преобразовать, довольно длинный.

Это делаетне похоже, что я могу предоставить отображение старого геттера getId() на новый getUniqueID().getValue(), например,

myObject.getId().equalsIgnoreCase("test")

потребуется сопоставить с

myObject.getUniqueID().getValue().equals(new Id("test"))

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

Есть ли автоматизированный способ сделать это?Может быть, какой-нибудь инструмент рефакторинга, который позволил бы указать, сколько лет шаблон использования будет отображаться в новом шаблоне использования?

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

Я думаю, что общий ответ на поставленный вопрос действительно заключается в использовании функциональности IntelliJ IDEA: Refactor → Перенос типов.

Проблема в том, что он, вероятно, перенесет множество других переменных в новый тип, ине только переменная, которую я хочу перенести.

Например, у нас есть другой класс NameDescription, который принимает два параметра String для имени и описания и иногда используется как new NameDescription(myObject.getId(), "Some description").В этом случае IDEA считает, что, вероятно, ей тоже нужно изменить NameDescription.name со строки на Id, что на самом деле неправильно.Чтобы избежать этого, необходимо предварительно просмотреть использование после запроса переноса типа и вручную исключить этот и другие случаи, которые не следует переносить.

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

Для обратной совместимости, как предполагает @ c0der, старый получатель вернет newIdObject.getValue()

0 голосов
/ 06 декабря 2018

Простое решение для обратной совместимости, которое не требует серьезного рефакторинга:

@Deprecated
String getId() {  return getUniqueID().getValue(); }

ID getUniqueID() {
    //TODO
}

Вручную редактируйте getId().getValue().equals("test") вхождений только в тех случаях, когда это необходимо и имеет явное преимущество.

...