Что можно сделать к кодовой базе прежней версии, которая окажет самое большое влияние на улучшение качества?

Что такое NullPointerException?

Хорошим местом для начала является JavaDocs . Они охватывают это:

Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  • Вызов метода экземпляра нулевого объекта.
  • Доступ или изменение поля нулевого объекта.
  • Выполнение длины null, как если бы это был массив.
  • Доступ или изменение слотов с нулевым значением, как если бы это был массив.
  • Бросать нуль, как если бы это было значение Throwable.

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

blockquote>

Также, если вы попытаетесь использовать нулевую ссылку с synchronized, который также выдаст это исключение, за JLS :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • В противном случае, если значение выражения равно null, NullPointerException.
blockquote>

Как это исправить?

Итак, у вас есть NullPointerException. Как вы это исправите? Возьмем простой пример, который выдает NullPointerException:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

Идентифицирует нулевые значения

. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

Здесь мы видим, что исключение выбрано в строке 13 (в методе printString). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, что s имеет значение null, а вызов метода length на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когда s.length() удаляется из метода.

Трассировка, где эти значения взяты из

Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что s передается с printString(name) в методе print(), а this.name - null.

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

Где установлен this.name? В методе setName(String). С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. ​​

Этого достаточно, чтобы дать нам решение: добавить вызов printer.setName() перед вызовом printer.print().

Другие исправления

Переменная может иметь значение по умолчанию setName может помешать ему установить значение null):

private String name = "";

Либо метод print, либо printString может проверить значение null например:

printString((name == null) ? "" : name);

Или вы можете создать класс, чтобы name всегда имел ненулевое значение :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

См. также:

Я все еще не могу найти проблему

Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).

39
задан Dariusz Woźniak 28 March 2019 в 09:50
поделиться

9 ответов

, Это - ЗАМЕЧАТЕЛЬНАЯ книга.

, Если бы Вам не нравится тот ответ, тогда лучший совет, я могу дать, был бы:

  • Первый, прекратите делать новый унаследованный код [1]

[1]: Унаследованный код = код без модульных тестов и поэтому неизвестного

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

ПРИМЕЧАНИЕ: я не говорю, что необходимо остановить все и провести недели, пишущий тесты для всего. Вполне обратное, просто протестируйте вокруг областей, которые необходимо протестировать и работать из там.

Jimmy Bogard и Ray Houston сделали интересный экран, набирает предмет, очень похожий на это: http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/05/06/pablotv-eliminating-static-dependencies-screencast.aspx

35
ответ дан chadmyers 27 November 2019 в 02:30
поделиться

Я работаю с наследием 1M приложение LOC, записанное и измененное приблизительно 50 программистами.

* Remove unused code

Почти бесполезный... просто игнорируют его. Вы привычка получаете большой Доход от инвестиций (ROI) от того.

* Remove duplicated code

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

* Add unit tests to improve test coverage where coverage is low

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

* Create consistent formatting across files

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

* Update 3rd party software

Делают это, только если существует новая действительно хорошая функция или версия, которую Вы имеете, не поддерживается новой операционной системой.

* Reduce warnings generated by static analysis tools

Это может стоящий того. Когда-то предупреждение может скрыть потенциальную ошибку.

21
ответ дан Hapkido 27 November 2019 в 02:30
поделиться

Добавьте модульные тесты для улучшения тестового покрытия. Наличие хорошего тестового покрытия позволит Вам осуществлять рефакторинг и улучшать функциональность без страха.

существует хорошая книга по записанному автором CPPUnit, Работа Эффективно с Унаследованным кодом .

Добавляющие тесты к унаследованному коду certianly более сложный, чем создание их с нуля. Самое полезное понятие я отнял у книги, является понятием "швов", которое Растушевки определяет как

"место, где можно изменить поведение в программе, не редактируя в том месте".

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

6
ответ дан Gordon Wilson 27 November 2019 в 02:30
поделиться

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

5
ответ дан James Inman 27 November 2019 в 02:30
поделиться

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

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

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

Остальное - действительно арахис. Это основные проблемы с кодовой базой прежней версии, они действительно съедают уйму времени.

3
ответ дан Caerbanog 27 November 2019 в 02:30
поделиться

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

, Если это неограниченно долго останется в режиме техобслуживания и это хорошо работает, делание ничего вообще является Вашим лучшим выбором. "Если это не, повредился, не фиксируйте его".

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

, Если Вы планируете версию 2.0, добавьте модульные тесты и очистите код, который Вы выдвинете

2
ответ дан Austin Salonen 27 November 2019 в 02:30
поделиться

Хорошая документация. Как кто-то, кто должен поддержать и расширить унаследованный код, который является проблемой номер один. Это трудно, если не совершенно опасный для изменения кода Вы не понимаете. Даже если Вам повезло быть врученными зарегистрированный код, насколько уверенный Вы, что документация является правильной? То, что это покрывает все неявное знание исходного автора? То, что это говорит со всеми "приемами" и пограничными случаями?

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

2
ответ дан Josh Segall 27 November 2019 в 02:30
поделиться

Единственная самая большая вещь, которую я сделал к унаследованному коду, с которым я должен работать, состоит в том, чтобы создать реальный API вокруг этого. Это - API КОБОЛа стиля 1970-х, что я создал объектную модель.NET вокруг, так, чтобы весь небезопасный код был в одном месте, весь перевод между собственными типами данных API и типами данных.NET находится в одном месте, основные методы возвращают и принимают DataSets и так далее.

Это было очень трудно сделать правильно, и существуют все еще некоторые дефекты в нем, что я знаю о. Это не ужасно эффективно также со всем маршалингом, который продолжается. Но с другой стороны, я могу создать DataGridView, что круговые данные к 15-летнему приложению, которое сохраняет его данные в Btrieve (!) приблизительно в полчаса, и это работает. Когда клиенты приезжают ко мне с проектами, мои оценки находятся в днях и неделях, а не месяцах и годах.

1
ответ дан Robert Rossney 27 November 2019 в 02:30
поделиться

Как параллель к тому, что сказал Josh Segall, который я скажу, комментируют ад из него. Я работал над несколькими очень большими унаследованными системами, которые были выведены в моей полировке, и я нашел, что самая большая проблема отслеживала, какого я уже узнал о конкретном разделе кода. Как только я начал помещать примечания, когда я иду, включая, "Чтобы Сделать" примечания, я прекратил повторно выяснять то, что я уже выяснил. Тогда я мог сфокусироваться о том, как те сегменты кода текут и взаимодействуют.

1
ответ дан dj_segfault 27 November 2019 в 02:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: